mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-14 15:46:32 +00:00
Revert "Renormalize line endings whitespace only after dccebddb3b80"
This reverts commit 9d98acb196a40fee5229afeb08f95fd36d41c10a.
This commit is contained in:
parent
e669bbbb72
commit
b55c52c047
@ -1,17 +1,17 @@
|
||||
# RUN: clangd -pretty -sync -input-mirror-file %t < %s
|
||||
# Note that we have to use '-b' as -input-mirror-file does not have a newline at the end of file.
|
||||
# RUN: diff -b %t %s
|
||||
# It is absolutely vital that this file has CRLF line endings.
|
||||
#
|
||||
Content-Length: 125
|
||||
|
||||
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
|
||||
Content-Length: 172
|
||||
|
||||
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"int main() {\nint a;\na;\n}\n"}}}
|
||||
Content-Length: 44
|
||||
|
||||
{"jsonrpc":"2.0","id":3,"method":"shutdown"}
|
||||
Content-Length: 33
|
||||
|
||||
{"jsonrpc":"2.0","method":"exit"}
|
||||
# RUN: clangd -pretty -sync -input-mirror-file %t < %s
|
||||
# Note that we have to use '-b' as -input-mirror-file does not have a newline at the end of file.
|
||||
# RUN: diff -b %t %s
|
||||
# It is absolutely vital that this file has CRLF line endings.
|
||||
#
|
||||
Content-Length: 125
|
||||
|
||||
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
|
||||
Content-Length: 172
|
||||
|
||||
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"int main() {\nint a;\na;\n}\n"}}}
|
||||
Content-Length: 44
|
||||
|
||||
{"jsonrpc":"2.0","id":3,"method":"shutdown"}
|
||||
Content-Length: 33
|
||||
|
||||
{"jsonrpc":"2.0","method":"exit"}
|
||||
|
@ -1,113 +1,113 @@
|
||||
# RUN: not clangd -pretty -sync -enable-test-uri-scheme < %s | FileCheck -strict-whitespace %s
|
||||
# RUN: not clangd -pretty -sync -enable-test-uri-scheme < %s 2>&1 | FileCheck -check-prefix=STDERR %s
|
||||
# vim: fileformat=dos
|
||||
# It is absolutely vital that this file has CRLF line endings.
|
||||
#
|
||||
# Note that we invert the test because we intent to let clangd exit prematurely.
|
||||
#
|
||||
# Test protocol parsing
|
||||
Content-Length: 125
|
||||
Content-Type: application/vscode-jsonrpc; charset-utf-8
|
||||
|
||||
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
|
||||
# Test message with Content-Type after Content-Length
|
||||
#
|
||||
# CHECK: "jsonrpc": "2.0",
|
||||
# CHECK-NEXT: "result": {
|
||||
# CHECK: }
|
||||
Content-Length: 246
|
||||
|
||||
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"struct fake { int a, bb, ccc; int f(int i, const float f) const; };\nint main() {\n fake f;\n f.\n}\n"}}}
|
||||
|
||||
Content-Length: 104
|
||||
|
||||
{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"test:///main.cpp"}}}
|
||||
|
||||
Content-Type: application/vscode-jsonrpc; charset-utf-8
|
||||
Content-Length: 146
|
||||
|
||||
{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}}
|
||||
# Test message with Content-Type before Content-Length
|
||||
#
|
||||
# CHECK: "id": 1,
|
||||
# CHECK-NEXT: "jsonrpc": "2.0",
|
||||
# CHECK-NEXT: "result": {
|
||||
# CHECK-NEXT: "isIncomplete": false,
|
||||
# CHECK-NEXT: "items": [
|
||||
# CHECK: "filterText": "a",
|
||||
# CHECK-NEXT: "insertText": "a",
|
||||
# CHECK-NEXT: "insertTextFormat": 1,
|
||||
# CHECK-NEXT: "kind": 5,
|
||||
# CHECK-NEXT: "label": " a",
|
||||
# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}},
|
||||
# CHECK-NEXT: "sortText": "{{.*}}"
|
||||
# CHECK: ]
|
||||
# CHECK-NEXT: }
|
||||
|
||||
X-Test: Testing
|
||||
Content-Type: application/vscode-jsonrpc; charset-utf-8
|
||||
Content-Length: 146
|
||||
Content-Type: application/vscode-jsonrpc; charset-utf-8
|
||||
X-Testing: Test
|
||||
|
||||
{"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}}
|
||||
|
||||
Content-Type: application/vscode-jsonrpc; charset-utf-8
|
||||
Content-Length: 10
|
||||
Content-Length: 146
|
||||
|
||||
{"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}}
|
||||
# Test message with duplicate Content-Length headers
|
||||
#
|
||||
# CHECK: "id": 3,
|
||||
# CHECK-NEXT: "jsonrpc": "2.0",
|
||||
# CHECK-NEXT: "result": {
|
||||
# CHECK-NEXT: "isIncomplete": false,
|
||||
# CHECK-NEXT: "items": [
|
||||
# CHECK: "filterText": "a",
|
||||
# CHECK-NEXT: "insertText": "a",
|
||||
# CHECK-NEXT: "insertTextFormat": 1,
|
||||
# CHECK-NEXT: "kind": 5,
|
||||
# CHECK-NEXT: "label": " a",
|
||||
# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}},
|
||||
# CHECK-NEXT: "sortText": "{{.*}}"
|
||||
# CHECK: ]
|
||||
# CHECK-NEXT: }
|
||||
# STDERR: Warning: Duplicate Content-Length header received. The previous value for this message (10) was ignored.
|
||||
|
||||
Content-Type: application/vscode-jsonrpc; charset-utf-8
|
||||
Content-Length: 10
|
||||
|
||||
{"jsonrpc":"2.0","id":4,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}}
|
||||
# Test message with malformed Content-Length
|
||||
#
|
||||
# STDERR: JSON parse error
|
||||
# Ensure we recover by sending another (valid) message
|
||||
|
||||
Content-Length: 146
|
||||
|
||||
{"jsonrpc":"2.0","id":5,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}}
|
||||
# Test message with Content-Type before Content-Length
|
||||
#
|
||||
# CHECK: "id": 5,
|
||||
# CHECK-NEXT: "jsonrpc": "2.0",
|
||||
# CHECK-NEXT: "result": {
|
||||
# CHECK-NEXT: "isIncomplete": false,
|
||||
# CHECK-NEXT: "items": [
|
||||
# CHECK: "filterText": "a",
|
||||
# CHECK-NEXT: "insertText": "a",
|
||||
# CHECK-NEXT: "insertTextFormat": 1,
|
||||
# CHECK-NEXT: "kind": 5,
|
||||
# CHECK-NEXT: "label": " a",
|
||||
# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}},
|
||||
# CHECK-NEXT: "sortText": "{{.*}}"
|
||||
# CHECK: ]
|
||||
# CHECK-NEXT: }
|
||||
Content-Length: 1024
|
||||
|
||||
{"jsonrpc":"2.0","id":5,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}}
|
||||
# Test message which reads beyond the end of the stream.
|
||||
#
|
||||
# Ensure this is the last test in the file!
|
||||
# STDERR: Input was aborted. Read only {{[0-9]+}} bytes of expected {{[0-9]+}}.
|
||||
|
||||
# RUN: not clangd -pretty -sync -enable-test-uri-scheme < %s | FileCheck -strict-whitespace %s
|
||||
# RUN: not clangd -pretty -sync -enable-test-uri-scheme < %s 2>&1 | FileCheck -check-prefix=STDERR %s
|
||||
# vim: fileformat=dos
|
||||
# It is absolutely vital that this file has CRLF line endings.
|
||||
#
|
||||
# Note that we invert the test because we intent to let clangd exit prematurely.
|
||||
#
|
||||
# Test protocol parsing
|
||||
Content-Length: 125
|
||||
Content-Type: application/vscode-jsonrpc; charset-utf-8
|
||||
|
||||
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
|
||||
# Test message with Content-Type after Content-Length
|
||||
#
|
||||
# CHECK: "jsonrpc": "2.0",
|
||||
# CHECK-NEXT: "result": {
|
||||
# CHECK: }
|
||||
Content-Length: 246
|
||||
|
||||
{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"struct fake { int a, bb, ccc; int f(int i, const float f) const; };\nint main() {\n fake f;\n f.\n}\n"}}}
|
||||
|
||||
Content-Length: 104
|
||||
|
||||
{"jsonrpc":"2.0","method":"textDocument/didChange","params":{"textDocument":{"uri":"test:///main.cpp"}}}
|
||||
|
||||
Content-Type: application/vscode-jsonrpc; charset-utf-8
|
||||
Content-Length: 146
|
||||
|
||||
{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}}
|
||||
# Test message with Content-Type before Content-Length
|
||||
#
|
||||
# CHECK: "id": 1,
|
||||
# CHECK-NEXT: "jsonrpc": "2.0",
|
||||
# CHECK-NEXT: "result": {
|
||||
# CHECK-NEXT: "isIncomplete": false,
|
||||
# CHECK-NEXT: "items": [
|
||||
# CHECK: "filterText": "a",
|
||||
# CHECK-NEXT: "insertText": "a",
|
||||
# CHECK-NEXT: "insertTextFormat": 1,
|
||||
# CHECK-NEXT: "kind": 5,
|
||||
# CHECK-NEXT: "label": " a",
|
||||
# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}},
|
||||
# CHECK-NEXT: "sortText": "{{.*}}"
|
||||
# CHECK: ]
|
||||
# CHECK-NEXT: }
|
||||
|
||||
X-Test: Testing
|
||||
Content-Type: application/vscode-jsonrpc; charset-utf-8
|
||||
Content-Length: 146
|
||||
Content-Type: application/vscode-jsonrpc; charset-utf-8
|
||||
X-Testing: Test
|
||||
|
||||
{"jsonrpc":"2.0","id":2,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}}
|
||||
|
||||
Content-Type: application/vscode-jsonrpc; charset-utf-8
|
||||
Content-Length: 10
|
||||
Content-Length: 146
|
||||
|
||||
{"jsonrpc":"2.0","id":3,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}}
|
||||
# Test message with duplicate Content-Length headers
|
||||
#
|
||||
# CHECK: "id": 3,
|
||||
# CHECK-NEXT: "jsonrpc": "2.0",
|
||||
# CHECK-NEXT: "result": {
|
||||
# CHECK-NEXT: "isIncomplete": false,
|
||||
# CHECK-NEXT: "items": [
|
||||
# CHECK: "filterText": "a",
|
||||
# CHECK-NEXT: "insertText": "a",
|
||||
# CHECK-NEXT: "insertTextFormat": 1,
|
||||
# CHECK-NEXT: "kind": 5,
|
||||
# CHECK-NEXT: "label": " a",
|
||||
# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}},
|
||||
# CHECK-NEXT: "sortText": "{{.*}}"
|
||||
# CHECK: ]
|
||||
# CHECK-NEXT: }
|
||||
# STDERR: Warning: Duplicate Content-Length header received. The previous value for this message (10) was ignored.
|
||||
|
||||
Content-Type: application/vscode-jsonrpc; charset-utf-8
|
||||
Content-Length: 10
|
||||
|
||||
{"jsonrpc":"2.0","id":4,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}}
|
||||
# Test message with malformed Content-Length
|
||||
#
|
||||
# STDERR: JSON parse error
|
||||
# Ensure we recover by sending another (valid) message
|
||||
|
||||
Content-Length: 146
|
||||
|
||||
{"jsonrpc":"2.0","id":5,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}}
|
||||
# Test message with Content-Type before Content-Length
|
||||
#
|
||||
# CHECK: "id": 5,
|
||||
# CHECK-NEXT: "jsonrpc": "2.0",
|
||||
# CHECK-NEXT: "result": {
|
||||
# CHECK-NEXT: "isIncomplete": false,
|
||||
# CHECK-NEXT: "items": [
|
||||
# CHECK: "filterText": "a",
|
||||
# CHECK-NEXT: "insertText": "a",
|
||||
# CHECK-NEXT: "insertTextFormat": 1,
|
||||
# CHECK-NEXT: "kind": 5,
|
||||
# CHECK-NEXT: "label": " a",
|
||||
# CHECK-NEXT: "score": {{[0-9]+.[0-9]+}},
|
||||
# CHECK-NEXT: "sortText": "{{.*}}"
|
||||
# CHECK: ]
|
||||
# CHECK-NEXT: }
|
||||
Content-Length: 1024
|
||||
|
||||
{"jsonrpc":"2.0","id":5,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:/main.cpp"},"position":{"line":3,"character":5}}}
|
||||
# Test message which reads beyond the end of the stream.
|
||||
#
|
||||
# Ensure this is the last test in the file!
|
||||
# STDERR: Input was aborted. Read only {{[0-9]+}} bytes of expected {{[0-9]+}}.
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
# RUN: not clangd -sync < %s 2>&1 | FileCheck -check-prefix=STDERR %s
|
||||
# vim: fileformat=dos
|
||||
# It is absolutely vital that this file has CRLF line endings.
|
||||
#
|
||||
Content-Length: 2147483648
|
||||
|
||||
# STDERR: Refusing to read message
|
||||
# RUN: not clangd -sync < %s 2>&1 | FileCheck -check-prefix=STDERR %s
|
||||
# vim: fileformat=dos
|
||||
# It is absolutely vital that this file has CRLF line endings.
|
||||
#
|
||||
Content-Length: 2147483648
|
||||
|
||||
# STDERR: Refusing to read message
|
||||
|
@ -1,64 +1,64 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY %s | FileCheck -check-prefix=EMPTY %s
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump %s | FileCheck %s
|
||||
|
||||
|
||||
// This test tests two different AST generations. The "EMPTY" test mode verifies
|
||||
// the AST generated by forward declaration of the HLSL types which happens on
|
||||
// initializing the HLSL external AST with an AST Context.
|
||||
|
||||
// The non-empty mode has a use that requires the StructuredBuffer type be complete,
|
||||
// which results in the AST being populated by the external AST source. That
|
||||
// case covers the full implementation of the template declaration and the
|
||||
// instantiated specialization.
|
||||
|
||||
// EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit StructuredBuffer
|
||||
// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
|
||||
// EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit <undeserialized declarations> class StructuredBuffer
|
||||
// EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
|
||||
|
||||
// There should be no more occurrances of StructuredBuffer
|
||||
// EMPTY-NOT: StructuredBuffer
|
||||
|
||||
#ifndef EMPTY
|
||||
|
||||
StructuredBuffer<float> Buffer;
|
||||
|
||||
#endif
|
||||
|
||||
// CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit StructuredBuffer
|
||||
// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
|
||||
// CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit class StructuredBuffer definition
|
||||
|
||||
// CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
|
||||
// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
|
||||
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit TypedBuffer
|
||||
|
||||
// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'element_type &const (unsigned int) const'
|
||||
// CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> Idx 'unsigned int'
|
||||
// CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
|
||||
// CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
|
||||
// CHECK-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'element_type' lvalue .e 0x{{[0-9A-Fa-f]+}}
|
||||
// CHECK-NEXT: CXXThisExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'const StructuredBuffer<element_type>' lvalue implicit this
|
||||
// CHECK-NEXT: AlwaysInlineAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit always_inline
|
||||
|
||||
// CHECK-NEXT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'element_type &(unsigned int)'
|
||||
// CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> Idx 'unsigned int'
|
||||
// CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
|
||||
// CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
|
||||
// CHECK-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'element_type' lvalue .e 0x{{[0-9A-Fa-f]+}}
|
||||
// CHECK-NEXT: CXXThisExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'StructuredBuffer<element_type>' lvalue implicit this
|
||||
// CHECK-NEXT: AlwaysInlineAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit always_inline
|
||||
|
||||
// CHECK: ClassTemplateSpecializationDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class StructuredBuffer definition
|
||||
|
||||
// CHECK: TemplateArgument type 'float'
|
||||
// CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'float'
|
||||
// CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
|
||||
// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(float)]]
|
||||
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit TypedBuffer
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump -DEMPTY %s | FileCheck -check-prefix=EMPTY %s
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -x hlsl -ast-dump %s | FileCheck %s
|
||||
|
||||
|
||||
// This test tests two different AST generations. The "EMPTY" test mode verifies
|
||||
// the AST generated by forward declaration of the HLSL types which happens on
|
||||
// initializing the HLSL external AST with an AST Context.
|
||||
|
||||
// The non-empty mode has a use that requires the StructuredBuffer type be complete,
|
||||
// which results in the AST being populated by the external AST source. That
|
||||
// case covers the full implementation of the template declaration and the
|
||||
// instantiated specialization.
|
||||
|
||||
// EMPTY: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit StructuredBuffer
|
||||
// EMPTY-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
|
||||
// EMPTY-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit <undeserialized declarations> class StructuredBuffer
|
||||
// EMPTY-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
|
||||
|
||||
// There should be no more occurrances of StructuredBuffer
|
||||
// EMPTY-NOT: StructuredBuffer
|
||||
|
||||
#ifndef EMPTY
|
||||
|
||||
StructuredBuffer<float> Buffer;
|
||||
|
||||
#endif
|
||||
|
||||
// CHECK: ClassTemplateDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit StructuredBuffer
|
||||
// CHECK-NEXT: TemplateTypeParmDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class depth 0 index 0 element_type
|
||||
// CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit class StructuredBuffer definition
|
||||
|
||||
// CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
|
||||
// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(element_type)]]
|
||||
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit TypedBuffer
|
||||
|
||||
// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'element_type &const (unsigned int) const'
|
||||
// CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> Idx 'unsigned int'
|
||||
// CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
|
||||
// CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
|
||||
// CHECK-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'element_type' lvalue .e 0x{{[0-9A-Fa-f]+}}
|
||||
// CHECK-NEXT: CXXThisExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'const StructuredBuffer<element_type>' lvalue implicit this
|
||||
// CHECK-NEXT: AlwaysInlineAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit always_inline
|
||||
|
||||
// CHECK-NEXT: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'element_type &(unsigned int)'
|
||||
// CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> Idx 'unsigned int'
|
||||
// CHECK-NEXT: CompoundStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
|
||||
// CHECK-NEXT: ReturnStmt 0x{{[0-9A-Fa-f]+}} <<invalid sloc>>
|
||||
// CHECK-NEXT: MemberExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'element_type' lvalue .e 0x{{[0-9A-Fa-f]+}}
|
||||
// CHECK-NEXT: CXXThisExpr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 'StructuredBuffer<element_type>' lvalue implicit this
|
||||
// CHECK-NEXT: AlwaysInlineAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit always_inline
|
||||
|
||||
// CHECK: ClassTemplateSpecializationDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> class StructuredBuffer definition
|
||||
|
||||
// CHECK: TemplateArgument type 'float'
|
||||
// CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'float'
|
||||
// CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
|
||||
// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(float)]]
|
||||
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit TypedBuffer
|
||||
|
@ -1,20 +1,20 @@
|
||||
// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
/* WG14 N3262: Yes
|
||||
* Usability of a byte-wise copy of va_list
|
||||
*
|
||||
* NB: Clang explicitly documents this as being undefined behavior. A
|
||||
* diagnostic is produced for some targets but not for others for assignment or
|
||||
* initialization, but no diagnostic is possible to produce for use with memcpy
|
||||
* in the general case, nor with a manual bytewise copy via a for loop.
|
||||
*
|
||||
* Therefore, nothing is tested in this file; it serves as a reminder that we
|
||||
* validated our documentation against the paper. See
|
||||
* clang/docs/LanguageExtensions.rst for more details.
|
||||
*
|
||||
* FIXME: it would be nice to add ubsan support for recognizing when an invalid
|
||||
* copy is made and diagnosing on copy (or on use of the copied va_list).
|
||||
*/
|
||||
|
||||
int main() {}
|
||||
// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
/* WG14 N3262: Yes
|
||||
* Usability of a byte-wise copy of va_list
|
||||
*
|
||||
* NB: Clang explicitly documents this as being undefined behavior. A
|
||||
* diagnostic is produced for some targets but not for others for assignment or
|
||||
* initialization, but no diagnostic is possible to produce for use with memcpy
|
||||
* in the general case, nor with a manual bytewise copy via a for loop.
|
||||
*
|
||||
* Therefore, nothing is tested in this file; it serves as a reminder that we
|
||||
* validated our documentation against the paper. See
|
||||
* clang/docs/LanguageExtensions.rst for more details.
|
||||
*
|
||||
* FIXME: it would be nice to add ubsan support for recognizing when an invalid
|
||||
* copy is made and diagnosing on copy (or on use of the copied va_list).
|
||||
*/
|
||||
|
||||
int main() {}
|
||||
|
@ -1,18 +1,18 @@
|
||||
// RUN: %clang_cc1 -verify -std=c23 -Wall -pedantic %s
|
||||
// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s
|
||||
|
||||
/* WG14 N3274: Yes
|
||||
* Remove imaginary types
|
||||
*/
|
||||
|
||||
// Clang has never supported _Imaginary.
|
||||
#ifdef __STDC_IEC_559_COMPLEX__
|
||||
#error "When did this happen?"
|
||||
#endif
|
||||
|
||||
_Imaginary float i; // expected-error {{imaginary types are not supported}}
|
||||
|
||||
// _Imaginary is a keyword in older language modes, but doesn't need to be one
|
||||
// in C2y or later. However, to improve diagnostic behavior, we retain it as a
|
||||
// keyword in all language modes -- it is not available as an identifier.
|
||||
static_assert(!__is_identifier(_Imaginary));
|
||||
// RUN: %clang_cc1 -verify -std=c23 -Wall -pedantic %s
|
||||
// RUN: %clang_cc1 -verify -std=c2y -Wall -pedantic %s
|
||||
|
||||
/* WG14 N3274: Yes
|
||||
* Remove imaginary types
|
||||
*/
|
||||
|
||||
// Clang has never supported _Imaginary.
|
||||
#ifdef __STDC_IEC_559_COMPLEX__
|
||||
#error "When did this happen?"
|
||||
#endif
|
||||
|
||||
_Imaginary float i; // expected-error {{imaginary types are not supported}}
|
||||
|
||||
// _Imaginary is a keyword in older language modes, but doesn't need to be one
|
||||
// in C2y or later. However, to improve diagnostic behavior, we retain it as a
|
||||
// keyword in all language modes -- it is not available as an identifier.
|
||||
static_assert(!__is_identifier(_Imaginary));
|
||||
|
@ -1,22 +1,22 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
|
||||
|
||||
StructuredBuffer<float> Buffer1;
|
||||
StructuredBuffer<vector<float, 4> > BufferArray[4];
|
||||
|
||||
StructuredBuffer<float> Buffer2 : register(u3);
|
||||
StructuredBuffer<vector<float, 4> > BufferArray2[4] : register(u4);
|
||||
|
||||
StructuredBuffer<float> Buffer3 : register(u3, space1);
|
||||
StructuredBuffer<vector<float, 4> > BufferArray3[4] : register(u4, space1);
|
||||
|
||||
[numthreads(1,1,1)]
|
||||
void main() {
|
||||
}
|
||||
|
||||
// CHECK: !hlsl.uavs = !{![[Single:[0-9]+]], ![[Array:[0-9]+]], ![[SingleAllocated:[0-9]+]], ![[ArrayAllocated:[0-9]+]], ![[SingleSpace:[0-9]+]], ![[ArraySpace:[0-9]+]]}
|
||||
// CHECK-DAG: ![[Single]] = !{ptr @Buffer1, i32 10, i32 9, i1 false, i32 -1, i32 0}
|
||||
// CHECK-DAG: ![[Array]] = !{ptr @BufferArray, i32 10, i32 9, i1 false, i32 -1, i32 0}
|
||||
// CHECK-DAG: ![[SingleAllocated]] = !{ptr @Buffer2, i32 10, i32 9, i1 false, i32 3, i32 0}
|
||||
// CHECK-DAG: ![[ArrayAllocated]] = !{ptr @BufferArray2, i32 10, i32 9, i1 false, i32 4, i32 0}
|
||||
// CHECK-DAG: ![[SingleSpace]] = !{ptr @Buffer3, i32 10, i32 9, i1 false, i32 3, i32 1}
|
||||
// CHECK-DAG: ![[ArraySpace]] = !{ptr @BufferArray3, i32 10, i32 9, i1 false, i32 4, i32 1}
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
|
||||
|
||||
StructuredBuffer<float> Buffer1;
|
||||
StructuredBuffer<vector<float, 4> > BufferArray[4];
|
||||
|
||||
StructuredBuffer<float> Buffer2 : register(u3);
|
||||
StructuredBuffer<vector<float, 4> > BufferArray2[4] : register(u4);
|
||||
|
||||
StructuredBuffer<float> Buffer3 : register(u3, space1);
|
||||
StructuredBuffer<vector<float, 4> > BufferArray3[4] : register(u4, space1);
|
||||
|
||||
[numthreads(1,1,1)]
|
||||
void main() {
|
||||
}
|
||||
|
||||
// CHECK: !hlsl.uavs = !{![[Single:[0-9]+]], ![[Array:[0-9]+]], ![[SingleAllocated:[0-9]+]], ![[ArrayAllocated:[0-9]+]], ![[SingleSpace:[0-9]+]], ![[ArraySpace:[0-9]+]]}
|
||||
// CHECK-DAG: ![[Single]] = !{ptr @Buffer1, i32 10, i32 9, i1 false, i32 -1, i32 0}
|
||||
// CHECK-DAG: ![[Array]] = !{ptr @BufferArray, i32 10, i32 9, i1 false, i32 -1, i32 0}
|
||||
// CHECK-DAG: ![[SingleAllocated]] = !{ptr @Buffer2, i32 10, i32 9, i1 false, i32 3, i32 0}
|
||||
// CHECK-DAG: ![[ArrayAllocated]] = !{ptr @BufferArray2, i32 10, i32 9, i1 false, i32 4, i32 0}
|
||||
// CHECK-DAG: ![[SingleSpace]] = !{ptr @Buffer3, i32 10, i32 9, i1 false, i32 3, i32 1}
|
||||
// CHECK-DAG: ![[ArraySpace]] = !{ptr @BufferArray3, i32 10, i32 9, i1 false, i32 4, i32 1}
|
||||
|
@ -1,70 +1,70 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
// NOTE: The number in type name and whether the struct is packed or not will mostly
|
||||
// likely change once subscript operators are properly implemented (llvm/llvm-project#95956)
|
||||
// and theinterim field of the contained type is removed.
|
||||
|
||||
// CHECK: %"class.hlsl::StructuredBuffer" = type <{ target("dx.RawBuffer", i16, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.0" = type <{ target("dx.RawBuffer", i16, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.2" = type { target("dx.RawBuffer", i32, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.3" = type { target("dx.RawBuffer", i32, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.4" = type { target("dx.RawBuffer", i64, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.5" = type { target("dx.RawBuffer", i64, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.6" = type <{ target("dx.RawBuffer", half, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.8" = type { target("dx.RawBuffer", float, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.9" = type { target("dx.RawBuffer", double, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.10" = type { target("dx.RawBuffer", <4 x i16>, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.11" = type { target("dx.RawBuffer", <3 x i32>, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.12" = type { target("dx.RawBuffer", <2 x half>, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.13" = type { target("dx.RawBuffer", <3 x float>, 1, 0)
|
||||
|
||||
StructuredBuffer<int16_t> BufI16;
|
||||
StructuredBuffer<uint16_t> BufU16;
|
||||
StructuredBuffer<int> BufI32;
|
||||
StructuredBuffer<uint> BufU32;
|
||||
StructuredBuffer<int64_t> BufI64;
|
||||
StructuredBuffer<uint64_t> BufU64;
|
||||
StructuredBuffer<half> BufF16;
|
||||
StructuredBuffer<float> BufF32;
|
||||
StructuredBuffer<double> BufF64;
|
||||
StructuredBuffer< vector<int16_t, 4> > BufI16x4;
|
||||
StructuredBuffer< vector<uint, 3> > BufU32x3;
|
||||
StructuredBuffer<half2> BufF16x2;
|
||||
StructuredBuffer<float3> BufF32x3;
|
||||
// TODO: StructuredBuffer<snorm half> BufSNormF16; -> 11
|
||||
// TODO: StructuredBuffer<unorm half> BufUNormF16; -> 12
|
||||
// TODO: StructuredBuffer<snorm float> BufSNormF32; -> 13
|
||||
// TODO: StructuredBuffer<unorm float> BufUNormF32; -> 14
|
||||
// TODO: StructuredBuffer<snorm double> BufSNormF64; -> 15
|
||||
// TODO: StructuredBuffer<unorm double> BufUNormF64; -> 16
|
||||
|
||||
[numthreads(1,1,1)]
|
||||
void main(int GI : SV_GroupIndex) {
|
||||
BufI16[GI] = 0;
|
||||
BufU16[GI] = 0;
|
||||
BufI32[GI] = 0;
|
||||
BufU32[GI] = 0;
|
||||
BufI64[GI] = 0;
|
||||
BufU64[GI] = 0;
|
||||
BufF16[GI] = 0;
|
||||
BufF32[GI] = 0;
|
||||
BufF64[GI] = 0;
|
||||
BufI16x4[GI] = 0;
|
||||
BufU32x3[GI] = 0;
|
||||
BufF16x2[GI] = 0;
|
||||
BufF32x3[GI] = 0;
|
||||
}
|
||||
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufI16, i32 10, i32 2,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufU16, i32 10, i32 3,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufI32, i32 10, i32 4,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufU32, i32 10, i32 5,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufI64, i32 10, i32 6,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufU64, i32 10, i32 7,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufF16, i32 10, i32 8,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufF32, i32 10, i32 9,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufF64, i32 10, i32 10,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufI16x4, i32 10, i32 2,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufU32x3, i32 10, i32 5,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufF16x2, i32 10, i32 8,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufF32x3, i32 10, i32 9,
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.2-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
// NOTE: The number in type name and whether the struct is packed or not will mostly
|
||||
// likely change once subscript operators are properly implemented (llvm/llvm-project#95956)
|
||||
// and theinterim field of the contained type is removed.
|
||||
|
||||
// CHECK: %"class.hlsl::StructuredBuffer" = type <{ target("dx.RawBuffer", i16, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.0" = type <{ target("dx.RawBuffer", i16, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.2" = type { target("dx.RawBuffer", i32, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.3" = type { target("dx.RawBuffer", i32, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.4" = type { target("dx.RawBuffer", i64, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.5" = type { target("dx.RawBuffer", i64, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.6" = type <{ target("dx.RawBuffer", half, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.8" = type { target("dx.RawBuffer", float, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.9" = type { target("dx.RawBuffer", double, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.10" = type { target("dx.RawBuffer", <4 x i16>, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.11" = type { target("dx.RawBuffer", <3 x i32>, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.12" = type { target("dx.RawBuffer", <2 x half>, 1, 0)
|
||||
// CHECK: %"class.hlsl::StructuredBuffer.13" = type { target("dx.RawBuffer", <3 x float>, 1, 0)
|
||||
|
||||
StructuredBuffer<int16_t> BufI16;
|
||||
StructuredBuffer<uint16_t> BufU16;
|
||||
StructuredBuffer<int> BufI32;
|
||||
StructuredBuffer<uint> BufU32;
|
||||
StructuredBuffer<int64_t> BufI64;
|
||||
StructuredBuffer<uint64_t> BufU64;
|
||||
StructuredBuffer<half> BufF16;
|
||||
StructuredBuffer<float> BufF32;
|
||||
StructuredBuffer<double> BufF64;
|
||||
StructuredBuffer< vector<int16_t, 4> > BufI16x4;
|
||||
StructuredBuffer< vector<uint, 3> > BufU32x3;
|
||||
StructuredBuffer<half2> BufF16x2;
|
||||
StructuredBuffer<float3> BufF32x3;
|
||||
// TODO: StructuredBuffer<snorm half> BufSNormF16; -> 11
|
||||
// TODO: StructuredBuffer<unorm half> BufUNormF16; -> 12
|
||||
// TODO: StructuredBuffer<snorm float> BufSNormF32; -> 13
|
||||
// TODO: StructuredBuffer<unorm float> BufUNormF32; -> 14
|
||||
// TODO: StructuredBuffer<snorm double> BufSNormF64; -> 15
|
||||
// TODO: StructuredBuffer<unorm double> BufUNormF64; -> 16
|
||||
|
||||
[numthreads(1,1,1)]
|
||||
void main(int GI : SV_GroupIndex) {
|
||||
BufI16[GI] = 0;
|
||||
BufU16[GI] = 0;
|
||||
BufI32[GI] = 0;
|
||||
BufU32[GI] = 0;
|
||||
BufI64[GI] = 0;
|
||||
BufU64[GI] = 0;
|
||||
BufF16[GI] = 0;
|
||||
BufF32[GI] = 0;
|
||||
BufF64[GI] = 0;
|
||||
BufI16x4[GI] = 0;
|
||||
BufU32x3[GI] = 0;
|
||||
BufF16x2[GI] = 0;
|
||||
BufF32x3[GI] = 0;
|
||||
}
|
||||
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufI16, i32 10, i32 2,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufU16, i32 10, i32 3,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufI32, i32 10, i32 4,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufU32, i32 10, i32 5,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufI64, i32 10, i32 6,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufU64, i32 10, i32 7,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufF16, i32 10, i32 8,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufF32, i32 10, i32 9,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufF64, i32 10, i32 10,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufI16x4, i32 10, i32 2,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufU32x3, i32 10, i32 5,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufF16x2, i32 10, i32 8,
|
||||
// CHECK: !{{[0-9]+}} = !{ptr @BufF32x3, i32 10, i32 9,
|
||||
|
@ -1,17 +1,17 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 %s | FileCheck %s
|
||||
|
||||
StructuredBuffer<int> In;
|
||||
StructuredBuffer<int> Out;
|
||||
|
||||
[numthreads(1,1,1)]
|
||||
void main(unsigned GI : SV_GroupIndex) {
|
||||
Out[GI] = In[GI];
|
||||
}
|
||||
|
||||
// Even at -O0 the subscript operators get inlined. The -O0 IR is a bit messy
|
||||
// and confusing to follow so the match here is pretty weak.
|
||||
|
||||
// CHECK: define void @main()
|
||||
// Verify inlining leaves only calls to "llvm." intrinsics
|
||||
// CHECK-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
|
||||
// CHECK: ret void
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -emit-llvm -o - -O0 %s | FileCheck %s
|
||||
|
||||
StructuredBuffer<int> In;
|
||||
StructuredBuffer<int> Out;
|
||||
|
||||
[numthreads(1,1,1)]
|
||||
void main(unsigned GI : SV_GroupIndex) {
|
||||
Out[GI] = In[GI];
|
||||
}
|
||||
|
||||
// Even at -O0 the subscript operators get inlined. The -O0 IR is a bit messy
|
||||
// and confusing to follow so the match here is pretty weak.
|
||||
|
||||
// CHECK: define void @main()
|
||||
// Verify inlining leaves only calls to "llvm." intrinsics
|
||||
// CHECK-NOT: call {{[^@]*}} @{{[^l][^l][^v][^m][^\.]}}
|
||||
// CHECK: ret void
|
||||
|
@ -1,59 +1,59 @@
|
||||
// RUN: %clang_cc1 -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 -finclude-default-header -x hlsl -triple \
|
||||
// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
|
||||
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
|
||||
|
||||
// CHECK-LABEL: test_atan2_half
|
||||
// NATIVE_HALF: call half @llvm.atan2.f16
|
||||
// NO_HALF: call float @llvm.atan2.f32
|
||||
half test_atan2_half (half p0, half p1) {
|
||||
return atan2(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_atan2_half2
|
||||
// NATIVE_HALF: call <2 x half> @llvm.atan2.v2f16
|
||||
// NO_HALF: call <2 x float> @llvm.atan2.v2f32
|
||||
half2 test_atan2_half2 (half2 p0, half2 p1) {
|
||||
return atan2(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_atan2_half3
|
||||
// NATIVE_HALF: call <3 x half> @llvm.atan2.v3f16
|
||||
// NO_HALF: call <3 x float> @llvm.atan2.v3f32
|
||||
half3 test_atan2_half3 (half3 p0, half3 p1) {
|
||||
return atan2(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_atan2_half4
|
||||
// NATIVE_HALF: call <4 x half> @llvm.atan2.v4f16
|
||||
// NO_HALF: call <4 x float> @llvm.atan2.v4f32
|
||||
half4 test_atan2_half4 (half4 p0, half4 p1) {
|
||||
return atan2(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_atan2_float
|
||||
// CHECK: call float @llvm.atan2.f32
|
||||
float test_atan2_float (float p0, float p1) {
|
||||
return atan2(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_atan2_float2
|
||||
// CHECK: call <2 x float> @llvm.atan2.v2f32
|
||||
float2 test_atan2_float2 (float2 p0, float2 p1) {
|
||||
return atan2(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_atan2_float3
|
||||
// CHECK: call <3 x float> @llvm.atan2.v3f32
|
||||
float3 test_atan2_float3 (float3 p0, float3 p1) {
|
||||
return atan2(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_atan2_float4
|
||||
// CHECK: call <4 x float> @llvm.atan2.v4f32
|
||||
float4 test_atan2_float4 (float4 p0, float4 p1) {
|
||||
return atan2(p0, p1);
|
||||
}
|
||||
// RUN: %clang_cc1 -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 -finclude-default-header -x hlsl -triple \
|
||||
// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
|
||||
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF
|
||||
|
||||
// CHECK-LABEL: test_atan2_half
|
||||
// NATIVE_HALF: call half @llvm.atan2.f16
|
||||
// NO_HALF: call float @llvm.atan2.f32
|
||||
half test_atan2_half (half p0, half p1) {
|
||||
return atan2(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_atan2_half2
|
||||
// NATIVE_HALF: call <2 x half> @llvm.atan2.v2f16
|
||||
// NO_HALF: call <2 x float> @llvm.atan2.v2f32
|
||||
half2 test_atan2_half2 (half2 p0, half2 p1) {
|
||||
return atan2(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_atan2_half3
|
||||
// NATIVE_HALF: call <3 x half> @llvm.atan2.v3f16
|
||||
// NO_HALF: call <3 x float> @llvm.atan2.v3f32
|
||||
half3 test_atan2_half3 (half3 p0, half3 p1) {
|
||||
return atan2(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_atan2_half4
|
||||
// NATIVE_HALF: call <4 x half> @llvm.atan2.v4f16
|
||||
// NO_HALF: call <4 x float> @llvm.atan2.v4f32
|
||||
half4 test_atan2_half4 (half4 p0, half4 p1) {
|
||||
return atan2(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_atan2_float
|
||||
// CHECK: call float @llvm.atan2.f32
|
||||
float test_atan2_float (float p0, float p1) {
|
||||
return atan2(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_atan2_float2
|
||||
// CHECK: call <2 x float> @llvm.atan2.v2f32
|
||||
float2 test_atan2_float2 (float2 p0, float2 p1) {
|
||||
return atan2(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_atan2_float3
|
||||
// CHECK: call <3 x float> @llvm.atan2.v3f32
|
||||
float3 test_atan2_float3 (float3 p0, float3 p1) {
|
||||
return atan2(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: test_atan2_float4
|
||||
// CHECK: call <4 x float> @llvm.atan2.v4f32
|
||||
float4 test_atan2_float4 (float4 p0, float4 p1) {
|
||||
return atan2(p0, p1);
|
||||
}
|
||||
|
@ -1,37 +1,37 @@
|
||||
// RUN: %clang_cc1 -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: -DFNATTRS=noundef -DTARGET=dx
|
||||
// RUN: %clang_cc1 -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 \
|
||||
// RUN: -DFNATTRS=noundef -DTARGET=dx
|
||||
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
|
||||
// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \
|
||||
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
|
||||
// RUN: --check-prefixes=CHECK,NATIVE_HALF \
|
||||
// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv
|
||||
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
|
||||
// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
|
||||
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \
|
||||
// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv
|
||||
|
||||
// NATIVE_HALF: define [[FNATTRS]] <3 x half> @
|
||||
// NATIVE_HALF: call <3 x half> @llvm.[[TARGET]].cross.v3f16(<3 x half>
|
||||
// NATIVE_HALF: ret <3 x half> %hlsl.cross
|
||||
// NO_HALF: define [[FNATTRS]] <3 x float> @
|
||||
// NO_HALF: call <3 x float> @llvm.[[TARGET]].cross.v3f32(<3 x float>
|
||||
// NO_HALF: ret <3 x float> %hlsl.cross
|
||||
half3 test_cross_half3(half3 p0, half3 p1)
|
||||
{
|
||||
return cross(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK: define [[FNATTRS]] <3 x float> @
|
||||
// CHECK: %hlsl.cross = call <3 x float> @llvm.[[TARGET]].cross.v3f32(
|
||||
// CHECK: ret <3 x float> %hlsl.cross
|
||||
float3 test_cross_float3(float3 p0, float3 p1)
|
||||
{
|
||||
return cross(p0, p1);
|
||||
}
|
||||
// RUN: %clang_cc1 -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: -DFNATTRS=noundef -DTARGET=dx
|
||||
// RUN: %clang_cc1 -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 \
|
||||
// RUN: -DFNATTRS=noundef -DTARGET=dx
|
||||
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
|
||||
// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \
|
||||
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
|
||||
// RUN: --check-prefixes=CHECK,NATIVE_HALF \
|
||||
// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv
|
||||
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
|
||||
// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
|
||||
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \
|
||||
// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv
|
||||
|
||||
// NATIVE_HALF: define [[FNATTRS]] <3 x half> @
|
||||
// NATIVE_HALF: call <3 x half> @llvm.[[TARGET]].cross.v3f16(<3 x half>
|
||||
// NATIVE_HALF: ret <3 x half> %hlsl.cross
|
||||
// NO_HALF: define [[FNATTRS]] <3 x float> @
|
||||
// NO_HALF: call <3 x float> @llvm.[[TARGET]].cross.v3f32(<3 x float>
|
||||
// NO_HALF: ret <3 x float> %hlsl.cross
|
||||
half3 test_cross_half3(half3 p0, half3 p1)
|
||||
{
|
||||
return cross(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK: define [[FNATTRS]] <3 x float> @
|
||||
// CHECK: %hlsl.cross = call <3 x float> @llvm.[[TARGET]].cross.v3f32(
|
||||
// CHECK: ret <3 x float> %hlsl.cross
|
||||
float3 test_cross_float3(float3 p0, float3 p1)
|
||||
{
|
||||
return cross(p0, p1);
|
||||
}
|
||||
|
@ -1,73 +1,73 @@
|
||||
// RUN: %clang_cc1 -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 -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
|
||||
|
||||
// NATIVE_HALF: define noundef half @
|
||||
// NATIVE_HALF: call half @llvm.fabs.f16(half
|
||||
// NO_HALF: call float @llvm.fabs.f32(float
|
||||
// NATIVE_HALF: ret half
|
||||
// NO_HALF: ret float
|
||||
half test_length_half(half p0)
|
||||
{
|
||||
return length(p0);
|
||||
}
|
||||
// NATIVE_HALF: define noundef half @
|
||||
// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v2f16
|
||||
// NO_HALF: %hlsl.length = call float @llvm.dx.length.v2f32(
|
||||
// NATIVE_HALF: ret half %hlsl.length
|
||||
// NO_HALF: ret float %hlsl.length
|
||||
half test_length_half2(half2 p0)
|
||||
{
|
||||
return length(p0);
|
||||
}
|
||||
// NATIVE_HALF: define noundef half @
|
||||
// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v3f16
|
||||
// NO_HALF: %hlsl.length = call float @llvm.dx.length.v3f32(
|
||||
// NATIVE_HALF: ret half %hlsl.length
|
||||
// NO_HALF: ret float %hlsl.length
|
||||
half test_length_half3(half3 p0)
|
||||
{
|
||||
return length(p0);
|
||||
}
|
||||
// NATIVE_HALF: define noundef half @
|
||||
// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v4f16
|
||||
// NO_HALF: %hlsl.length = call float @llvm.dx.length.v4f32(
|
||||
// NATIVE_HALF: ret half %hlsl.length
|
||||
// NO_HALF: ret float %hlsl.length
|
||||
half test_length_half4(half4 p0)
|
||||
{
|
||||
return length(p0);
|
||||
}
|
||||
|
||||
// CHECK: define noundef float @
|
||||
// CHECK: call float @llvm.fabs.f32(float
|
||||
// CHECK: ret float
|
||||
float test_length_float(float p0)
|
||||
{
|
||||
return length(p0);
|
||||
}
|
||||
// CHECK: define noundef float @
|
||||
// CHECK: %hlsl.length = call float @llvm.dx.length.v2f32(
|
||||
// CHECK: ret float %hlsl.length
|
||||
float test_length_float2(float2 p0)
|
||||
{
|
||||
return length(p0);
|
||||
}
|
||||
// CHECK: define noundef float @
|
||||
// CHECK: %hlsl.length = call float @llvm.dx.length.v3f32(
|
||||
// CHECK: ret float %hlsl.length
|
||||
float test_length_float3(float3 p0)
|
||||
{
|
||||
return length(p0);
|
||||
}
|
||||
// CHECK: define noundef float @
|
||||
// CHECK: %hlsl.length = call float @llvm.dx.length.v4f32(
|
||||
// CHECK: ret float %hlsl.length
|
||||
float test_length_float4(float4 p0)
|
||||
{
|
||||
return length(p0);
|
||||
}
|
||||
// RUN: %clang_cc1 -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 -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
|
||||
|
||||
// NATIVE_HALF: define noundef half @
|
||||
// NATIVE_HALF: call half @llvm.fabs.f16(half
|
||||
// NO_HALF: call float @llvm.fabs.f32(float
|
||||
// NATIVE_HALF: ret half
|
||||
// NO_HALF: ret float
|
||||
half test_length_half(half p0)
|
||||
{
|
||||
return length(p0);
|
||||
}
|
||||
// NATIVE_HALF: define noundef half @
|
||||
// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v2f16
|
||||
// NO_HALF: %hlsl.length = call float @llvm.dx.length.v2f32(
|
||||
// NATIVE_HALF: ret half %hlsl.length
|
||||
// NO_HALF: ret float %hlsl.length
|
||||
half test_length_half2(half2 p0)
|
||||
{
|
||||
return length(p0);
|
||||
}
|
||||
// NATIVE_HALF: define noundef half @
|
||||
// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v3f16
|
||||
// NO_HALF: %hlsl.length = call float @llvm.dx.length.v3f32(
|
||||
// NATIVE_HALF: ret half %hlsl.length
|
||||
// NO_HALF: ret float %hlsl.length
|
||||
half test_length_half3(half3 p0)
|
||||
{
|
||||
return length(p0);
|
||||
}
|
||||
// NATIVE_HALF: define noundef half @
|
||||
// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v4f16
|
||||
// NO_HALF: %hlsl.length = call float @llvm.dx.length.v4f32(
|
||||
// NATIVE_HALF: ret half %hlsl.length
|
||||
// NO_HALF: ret float %hlsl.length
|
||||
half test_length_half4(half4 p0)
|
||||
{
|
||||
return length(p0);
|
||||
}
|
||||
|
||||
// CHECK: define noundef float @
|
||||
// CHECK: call float @llvm.fabs.f32(float
|
||||
// CHECK: ret float
|
||||
float test_length_float(float p0)
|
||||
{
|
||||
return length(p0);
|
||||
}
|
||||
// CHECK: define noundef float @
|
||||
// CHECK: %hlsl.length = call float @llvm.dx.length.v2f32(
|
||||
// CHECK: ret float %hlsl.length
|
||||
float test_length_float2(float2 p0)
|
||||
{
|
||||
return length(p0);
|
||||
}
|
||||
// CHECK: define noundef float @
|
||||
// CHECK: %hlsl.length = call float @llvm.dx.length.v3f32(
|
||||
// CHECK: ret float %hlsl.length
|
||||
float test_length_float3(float3 p0)
|
||||
{
|
||||
return length(p0);
|
||||
}
|
||||
// CHECK: define noundef float @
|
||||
// CHECK: %hlsl.length = call float @llvm.dx.length.v4f32(
|
||||
// CHECK: ret float %hlsl.length
|
||||
float test_length_float4(float4 p0)
|
||||
{
|
||||
return length(p0);
|
||||
}
|
||||
|
@ -1,85 +1,85 @@
|
||||
// RUN: %clang_cc1 -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: -DFNATTRS=noundef -DTARGET=dx
|
||||
// RUN: %clang_cc1 -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 \
|
||||
// RUN: -DFNATTRS=noundef -DTARGET=dx
|
||||
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
|
||||
// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \
|
||||
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
|
||||
// RUN: --check-prefixes=CHECK,NATIVE_HALF \
|
||||
// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv
|
||||
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
|
||||
// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
|
||||
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \
|
||||
// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv
|
||||
|
||||
// NATIVE_HALF: define [[FNATTRS]] half @
|
||||
// NATIVE_HALF: call half @llvm.[[TARGET]].normalize.f16(half
|
||||
// NO_HALF: call float @llvm.[[TARGET]].normalize.f32(float
|
||||
// NATIVE_HALF: ret half
|
||||
// NO_HALF: ret float
|
||||
half test_normalize_half(half p0)
|
||||
{
|
||||
return normalize(p0);
|
||||
}
|
||||
// NATIVE_HALF: define [[FNATTRS]] <2 x half> @
|
||||
// NATIVE_HALF: call <2 x half> @llvm.[[TARGET]].normalize.v2f16(<2 x half>
|
||||
// NO_HALF: call <2 x float> @llvm.[[TARGET]].normalize.v2f32(<2 x float>
|
||||
// NATIVE_HALF: ret <2 x half> %hlsl.normalize
|
||||
// NO_HALF: ret <2 x float> %hlsl.normalize
|
||||
half2 test_normalize_half2(half2 p0)
|
||||
{
|
||||
return normalize(p0);
|
||||
}
|
||||
// NATIVE_HALF: define [[FNATTRS]] <3 x half> @
|
||||
// NATIVE_HALF: call <3 x half> @llvm.[[TARGET]].normalize.v3f16(<3 x half>
|
||||
// NO_HALF: call <3 x float> @llvm.[[TARGET]].normalize.v3f32(<3 x float>
|
||||
// NATIVE_HALF: ret <3 x half> %hlsl.normalize
|
||||
// NO_HALF: ret <3 x float> %hlsl.normalize
|
||||
half3 test_normalize_half3(half3 p0)
|
||||
{
|
||||
return normalize(p0);
|
||||
}
|
||||
// NATIVE_HALF: define [[FNATTRS]] <4 x half> @
|
||||
// NATIVE_HALF: call <4 x half> @llvm.[[TARGET]].normalize.v4f16(<4 x half>
|
||||
// NO_HALF: call <4 x float> @llvm.[[TARGET]].normalize.v4f32(<4 x float>
|
||||
// NATIVE_HALF: ret <4 x half> %hlsl.normalize
|
||||
// NO_HALF: ret <4 x float> %hlsl.normalize
|
||||
half4 test_normalize_half4(half4 p0)
|
||||
{
|
||||
return normalize(p0);
|
||||
}
|
||||
|
||||
// CHECK: define [[FNATTRS]] float @
|
||||
// CHECK: call float @llvm.[[TARGET]].normalize.f32(float
|
||||
// CHECK: ret float
|
||||
float test_normalize_float(float p0)
|
||||
{
|
||||
return normalize(p0);
|
||||
}
|
||||
// CHECK: define [[FNATTRS]] <2 x float> @
|
||||
// CHECK: %hlsl.normalize = call <2 x float> @llvm.[[TARGET]].normalize.v2f32(<2 x float>
|
||||
|
||||
// CHECK: ret <2 x float> %hlsl.normalize
|
||||
float2 test_normalize_float2(float2 p0)
|
||||
{
|
||||
return normalize(p0);
|
||||
}
|
||||
// CHECK: define [[FNATTRS]] <3 x float> @
|
||||
// CHECK: %hlsl.normalize = call <3 x float> @llvm.[[TARGET]].normalize.v3f32(
|
||||
// CHECK: ret <3 x float> %hlsl.normalize
|
||||
float3 test_normalize_float3(float3 p0)
|
||||
{
|
||||
return normalize(p0);
|
||||
}
|
||||
// CHECK: define [[FNATTRS]] <4 x float> @
|
||||
// CHECK: %hlsl.normalize = call <4 x float> @llvm.[[TARGET]].normalize.v4f32(
|
||||
// CHECK: ret <4 x float> %hlsl.normalize
|
||||
float4 test_length_float4(float4 p0)
|
||||
{
|
||||
return normalize(p0);
|
||||
}
|
||||
// RUN: %clang_cc1 -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: -DFNATTRS=noundef -DTARGET=dx
|
||||
// RUN: %clang_cc1 -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 \
|
||||
// RUN: -DFNATTRS=noundef -DTARGET=dx
|
||||
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
|
||||
// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \
|
||||
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
|
||||
// RUN: --check-prefixes=CHECK,NATIVE_HALF \
|
||||
// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv
|
||||
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
|
||||
// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
|
||||
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \
|
||||
// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv
|
||||
|
||||
// NATIVE_HALF: define [[FNATTRS]] half @
|
||||
// NATIVE_HALF: call half @llvm.[[TARGET]].normalize.f16(half
|
||||
// NO_HALF: call float @llvm.[[TARGET]].normalize.f32(float
|
||||
// NATIVE_HALF: ret half
|
||||
// NO_HALF: ret float
|
||||
half test_normalize_half(half p0)
|
||||
{
|
||||
return normalize(p0);
|
||||
}
|
||||
// NATIVE_HALF: define [[FNATTRS]] <2 x half> @
|
||||
// NATIVE_HALF: call <2 x half> @llvm.[[TARGET]].normalize.v2f16(<2 x half>
|
||||
// NO_HALF: call <2 x float> @llvm.[[TARGET]].normalize.v2f32(<2 x float>
|
||||
// NATIVE_HALF: ret <2 x half> %hlsl.normalize
|
||||
// NO_HALF: ret <2 x float> %hlsl.normalize
|
||||
half2 test_normalize_half2(half2 p0)
|
||||
{
|
||||
return normalize(p0);
|
||||
}
|
||||
// NATIVE_HALF: define [[FNATTRS]] <3 x half> @
|
||||
// NATIVE_HALF: call <3 x half> @llvm.[[TARGET]].normalize.v3f16(<3 x half>
|
||||
// NO_HALF: call <3 x float> @llvm.[[TARGET]].normalize.v3f32(<3 x float>
|
||||
// NATIVE_HALF: ret <3 x half> %hlsl.normalize
|
||||
// NO_HALF: ret <3 x float> %hlsl.normalize
|
||||
half3 test_normalize_half3(half3 p0)
|
||||
{
|
||||
return normalize(p0);
|
||||
}
|
||||
// NATIVE_HALF: define [[FNATTRS]] <4 x half> @
|
||||
// NATIVE_HALF: call <4 x half> @llvm.[[TARGET]].normalize.v4f16(<4 x half>
|
||||
// NO_HALF: call <4 x float> @llvm.[[TARGET]].normalize.v4f32(<4 x float>
|
||||
// NATIVE_HALF: ret <4 x half> %hlsl.normalize
|
||||
// NO_HALF: ret <4 x float> %hlsl.normalize
|
||||
half4 test_normalize_half4(half4 p0)
|
||||
{
|
||||
return normalize(p0);
|
||||
}
|
||||
|
||||
// CHECK: define [[FNATTRS]] float @
|
||||
// CHECK: call float @llvm.[[TARGET]].normalize.f32(float
|
||||
// CHECK: ret float
|
||||
float test_normalize_float(float p0)
|
||||
{
|
||||
return normalize(p0);
|
||||
}
|
||||
// CHECK: define [[FNATTRS]] <2 x float> @
|
||||
// CHECK: %hlsl.normalize = call <2 x float> @llvm.[[TARGET]].normalize.v2f32(<2 x float>
|
||||
|
||||
// CHECK: ret <2 x float> %hlsl.normalize
|
||||
float2 test_normalize_float2(float2 p0)
|
||||
{
|
||||
return normalize(p0);
|
||||
}
|
||||
// CHECK: define [[FNATTRS]] <3 x float> @
|
||||
// CHECK: %hlsl.normalize = call <3 x float> @llvm.[[TARGET]].normalize.v3f32(
|
||||
// CHECK: ret <3 x float> %hlsl.normalize
|
||||
float3 test_normalize_float3(float3 p0)
|
||||
{
|
||||
return normalize(p0);
|
||||
}
|
||||
// CHECK: define [[FNATTRS]] <4 x float> @
|
||||
// CHECK: %hlsl.normalize = call <4 x float> @llvm.[[TARGET]].normalize.v4f32(
|
||||
// CHECK: ret <4 x float> %hlsl.normalize
|
||||
float4 test_length_float4(float4 p0)
|
||||
{
|
||||
return normalize(p0);
|
||||
}
|
||||
|
@ -1,84 +1,84 @@
|
||||
// RUN: %clang_cc1 -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: -DFNATTRS=noundef -DTARGET=dx
|
||||
// RUN: %clang_cc1 -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 \
|
||||
// RUN: -DFNATTRS=noundef -DTARGET=dx
|
||||
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
|
||||
// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \
|
||||
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
|
||||
// RUN: --check-prefixes=CHECK,NATIVE_HALF \
|
||||
// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv
|
||||
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
|
||||
// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
|
||||
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \
|
||||
// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv
|
||||
|
||||
// NATIVE_HALF: define [[FNATTRS]] half @
|
||||
// NATIVE_HALF: call half @llvm.[[TARGET]].step.f16(half
|
||||
// NO_HALF: call float @llvm.[[TARGET]].step.f32(float
|
||||
// NATIVE_HALF: ret half
|
||||
// NO_HALF: ret float
|
||||
half test_step_half(half p0, half p1)
|
||||
{
|
||||
return step(p0, p1);
|
||||
}
|
||||
// NATIVE_HALF: define [[FNATTRS]] <2 x half> @
|
||||
// NATIVE_HALF: call <2 x half> @llvm.[[TARGET]].step.v2f16(<2 x half>
|
||||
// NO_HALF: call <2 x float> @llvm.[[TARGET]].step.v2f32(<2 x float>
|
||||
// NATIVE_HALF: ret <2 x half> %hlsl.step
|
||||
// NO_HALF: ret <2 x float> %hlsl.step
|
||||
half2 test_step_half2(half2 p0, half2 p1)
|
||||
{
|
||||
return step(p0, p1);
|
||||
}
|
||||
// NATIVE_HALF: define [[FNATTRS]] <3 x half> @
|
||||
// NATIVE_HALF: call <3 x half> @llvm.[[TARGET]].step.v3f16(<3 x half>
|
||||
// NO_HALF: call <3 x float> @llvm.[[TARGET]].step.v3f32(<3 x float>
|
||||
// NATIVE_HALF: ret <3 x half> %hlsl.step
|
||||
// NO_HALF: ret <3 x float> %hlsl.step
|
||||
half3 test_step_half3(half3 p0, half3 p1)
|
||||
{
|
||||
return step(p0, p1);
|
||||
}
|
||||
// NATIVE_HALF: define [[FNATTRS]] <4 x half> @
|
||||
// NATIVE_HALF: call <4 x half> @llvm.[[TARGET]].step.v4f16(<4 x half>
|
||||
// NO_HALF: call <4 x float> @llvm.[[TARGET]].step.v4f32(<4 x float>
|
||||
// NATIVE_HALF: ret <4 x half> %hlsl.step
|
||||
// NO_HALF: ret <4 x float> %hlsl.step
|
||||
half4 test_step_half4(half4 p0, half4 p1)
|
||||
{
|
||||
return step(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK: define [[FNATTRS]] float @
|
||||
// CHECK: call float @llvm.[[TARGET]].step.f32(float
|
||||
// CHECK: ret float
|
||||
float test_step_float(float p0, float p1)
|
||||
{
|
||||
return step(p0, p1);
|
||||
}
|
||||
// CHECK: define [[FNATTRS]] <2 x float> @
|
||||
// CHECK: %hlsl.step = call <2 x float> @llvm.[[TARGET]].step.v2f32(
|
||||
// CHECK: ret <2 x float> %hlsl.step
|
||||
float2 test_step_float2(float2 p0, float2 p1)
|
||||
{
|
||||
return step(p0, p1);
|
||||
}
|
||||
// CHECK: define [[FNATTRS]] <3 x float> @
|
||||
// CHECK: %hlsl.step = call <3 x float> @llvm.[[TARGET]].step.v3f32(
|
||||
// CHECK: ret <3 x float> %hlsl.step
|
||||
float3 test_step_float3(float3 p0, float3 p1)
|
||||
{
|
||||
return step(p0, p1);
|
||||
}
|
||||
// CHECK: define [[FNATTRS]] <4 x float> @
|
||||
// CHECK: %hlsl.step = call <4 x float> @llvm.[[TARGET]].step.v4f32(
|
||||
// CHECK: ret <4 x float> %hlsl.step
|
||||
float4 test_step_float4(float4 p0, float4 p1)
|
||||
{
|
||||
return step(p0, p1);
|
||||
}
|
||||
// RUN: %clang_cc1 -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: -DFNATTRS=noundef -DTARGET=dx
|
||||
// RUN: %clang_cc1 -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 \
|
||||
// RUN: -DFNATTRS=noundef -DTARGET=dx
|
||||
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
|
||||
// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \
|
||||
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
|
||||
// RUN: --check-prefixes=CHECK,NATIVE_HALF \
|
||||
// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv
|
||||
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
|
||||
// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
|
||||
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \
|
||||
// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv
|
||||
|
||||
// NATIVE_HALF: define [[FNATTRS]] half @
|
||||
// NATIVE_HALF: call half @llvm.[[TARGET]].step.f16(half
|
||||
// NO_HALF: call float @llvm.[[TARGET]].step.f32(float
|
||||
// NATIVE_HALF: ret half
|
||||
// NO_HALF: ret float
|
||||
half test_step_half(half p0, half p1)
|
||||
{
|
||||
return step(p0, p1);
|
||||
}
|
||||
// NATIVE_HALF: define [[FNATTRS]] <2 x half> @
|
||||
// NATIVE_HALF: call <2 x half> @llvm.[[TARGET]].step.v2f16(<2 x half>
|
||||
// NO_HALF: call <2 x float> @llvm.[[TARGET]].step.v2f32(<2 x float>
|
||||
// NATIVE_HALF: ret <2 x half> %hlsl.step
|
||||
// NO_HALF: ret <2 x float> %hlsl.step
|
||||
half2 test_step_half2(half2 p0, half2 p1)
|
||||
{
|
||||
return step(p0, p1);
|
||||
}
|
||||
// NATIVE_HALF: define [[FNATTRS]] <3 x half> @
|
||||
// NATIVE_HALF: call <3 x half> @llvm.[[TARGET]].step.v3f16(<3 x half>
|
||||
// NO_HALF: call <3 x float> @llvm.[[TARGET]].step.v3f32(<3 x float>
|
||||
// NATIVE_HALF: ret <3 x half> %hlsl.step
|
||||
// NO_HALF: ret <3 x float> %hlsl.step
|
||||
half3 test_step_half3(half3 p0, half3 p1)
|
||||
{
|
||||
return step(p0, p1);
|
||||
}
|
||||
// NATIVE_HALF: define [[FNATTRS]] <4 x half> @
|
||||
// NATIVE_HALF: call <4 x half> @llvm.[[TARGET]].step.v4f16(<4 x half>
|
||||
// NO_HALF: call <4 x float> @llvm.[[TARGET]].step.v4f32(<4 x float>
|
||||
// NATIVE_HALF: ret <4 x half> %hlsl.step
|
||||
// NO_HALF: ret <4 x float> %hlsl.step
|
||||
half4 test_step_half4(half4 p0, half4 p1)
|
||||
{
|
||||
return step(p0, p1);
|
||||
}
|
||||
|
||||
// CHECK: define [[FNATTRS]] float @
|
||||
// CHECK: call float @llvm.[[TARGET]].step.f32(float
|
||||
// CHECK: ret float
|
||||
float test_step_float(float p0, float p1)
|
||||
{
|
||||
return step(p0, p1);
|
||||
}
|
||||
// CHECK: define [[FNATTRS]] <2 x float> @
|
||||
// CHECK: %hlsl.step = call <2 x float> @llvm.[[TARGET]].step.v2f32(
|
||||
// CHECK: ret <2 x float> %hlsl.step
|
||||
float2 test_step_float2(float2 p0, float2 p1)
|
||||
{
|
||||
return step(p0, p1);
|
||||
}
|
||||
// CHECK: define [[FNATTRS]] <3 x float> @
|
||||
// CHECK: %hlsl.step = call <3 x float> @llvm.[[TARGET]].step.v3f32(
|
||||
// CHECK: ret <3 x float> %hlsl.step
|
||||
float3 test_step_float3(float3 p0, float3 p1)
|
||||
{
|
||||
return step(p0, p1);
|
||||
}
|
||||
// CHECK: define [[FNATTRS]] <4 x float> @
|
||||
// CHECK: %hlsl.step = call <4 x float> @llvm.[[TARGET]].step.v4f32(
|
||||
// CHECK: ret <4 x float> %hlsl.step
|
||||
float4 test_step_float4(float4 p0, float4 p1)
|
||||
{
|
||||
return step(p0, p1);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
! RUN: %clang --driver-mode=flang --target=x86_64-pc-windows-msvc -### %s -Ltest 2>&1 | FileCheck %s
|
||||
!
|
||||
! Test that user provided paths come before the Flang runtimes
|
||||
! CHECK: "-libpath:test"
|
||||
! CHECK: "-libpath:{{.*(\\|/)}}lib"
|
||||
! RUN: %clang --driver-mode=flang --target=x86_64-pc-windows-msvc -### %s -Ltest 2>&1 | FileCheck %s
|
||||
!
|
||||
! Test that user provided paths come before the Flang runtimes
|
||||
! CHECK: "-libpath:test"
|
||||
! CHECK: "-libpath:{{.*(\\|/)}}lib"
|
||||
|
@ -1,11 +1,11 @@
|
||||
// RUN: %clang_cc1 -pedantic -Wunused-label -fno-diagnostics-show-line-numbers -x c %s 2>&1 | FileCheck %s -strict-whitespace
|
||||
|
||||
// This file intentionally uses a CRLF newline style
|
||||
// CHECK: warning: unused label 'ddd'
|
||||
// CHECK-NEXT: {{^ ddd:}}
|
||||
// CHECK-NEXT: {{^ \^~~~$}}
|
||||
// CHECK-NOT: {{^ ;}}
|
||||
void f(void) {
|
||||
ddd:
|
||||
;
|
||||
}
|
||||
// RUN: %clang_cc1 -pedantic -Wunused-label -fno-diagnostics-show-line-numbers -x c %s 2>&1 | FileCheck %s -strict-whitespace
|
||||
|
||||
// This file intentionally uses a CRLF newline style
|
||||
// CHECK: warning: unused label 'ddd'
|
||||
// CHECK-NEXT: {{^ ddd:}}
|
||||
// CHECK-NEXT: {{^ \^~~~$}}
|
||||
// CHECK-NOT: {{^ ;}}
|
||||
void f(void) {
|
||||
ddd:
|
||||
;
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
// RUN: %clang_cc1 -E -frewrite-includes %s | %clang_cc1 -
|
||||
// expected-no-diagnostics
|
||||
// Note: This source file has CRLF line endings.
|
||||
// This test validates that -frewrite-includes translates the end of line (EOL)
|
||||
// form used in header files to the EOL form used in the the primary source
|
||||
// file when the files use different EOL forms.
|
||||
#include "rewrite-includes-mixed-eol-crlf.h"
|
||||
#include "rewrite-includes-mixed-eol-lf.h"
|
||||
// RUN: %clang_cc1 -E -frewrite-includes %s | %clang_cc1 -
|
||||
// expected-no-diagnostics
|
||||
// Note: This source file has CRLF line endings.
|
||||
// This test validates that -frewrite-includes translates the end of line (EOL)
|
||||
// form used in header files to the EOL form used in the the primary source
|
||||
// file when the files use different EOL forms.
|
||||
#include "rewrite-includes-mixed-eol-crlf.h"
|
||||
#include "rewrite-includes-mixed-eol-lf.h"
|
||||
|
@ -1,11 +1,11 @@
|
||||
// Note: This header file has CRLF line endings.
|
||||
// The indentation in some of the conditional inclusion directives below is
|
||||
// intentional and is required for this test to function as a regression test
|
||||
// for GH59736.
|
||||
_Static_assert(__LINE__ == 5, "");
|
||||
#if 1
|
||||
_Static_assert(__LINE__ == 7, "");
|
||||
#if 1
|
||||
_Static_assert(__LINE__ == 9, "");
|
||||
#endif
|
||||
#endif
|
||||
// Note: This header file has CRLF line endings.
|
||||
// The indentation in some of the conditional inclusion directives below is
|
||||
// intentional and is required for this test to function as a regression test
|
||||
// for GH59736.
|
||||
_Static_assert(__LINE__ == 5, "");
|
||||
#if 1
|
||||
_Static_assert(__LINE__ == 7, "");
|
||||
#if 1
|
||||
_Static_assert(__LINE__ == 9, "");
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,21 +1,21 @@
|
||||
// RUN: %clang_cc1 %s -E -o - -I %S/Inputs -isystem %S/Inputs/SystemHeaderPrefix | FileCheck %s
|
||||
#include <noline.h>
|
||||
#include <line-directive-in-system.h>
|
||||
|
||||
#include "line-directive.h"
|
||||
|
||||
// This tests that the line numbers for the current file are correctly outputted
|
||||
// for the include-file-completed test case. This file should be CRLF.
|
||||
|
||||
// CHECK: # 1 "{{.*}}system-header-line-directive-ms-lineendings.c" 2
|
||||
// CHECK: # 1 "{{.*}}noline.h" 1 3
|
||||
// CHECK: foo(void);
|
||||
// CHECK: # 3 "{{.*}}system-header-line-directive-ms-lineendings.c" 2
|
||||
// CHECK: # 1 "{{.*}}line-directive-in-system.h" 1 3
|
||||
// The "3" below indicates that "foo.h" is considered a system header.
|
||||
// CHECK: # 1 "foo.h" 3
|
||||
// CHECK: foo(void);
|
||||
// CHECK: # 4 "{{.*}}system-header-line-directive-ms-lineendings.c" 2
|
||||
// CHECK: # 1 "{{.*}}line-directive.h" 1
|
||||
// CHECK: # 10 "foo.h"{{$}}
|
||||
// CHECK: # 6 "{{.*}}system-header-line-directive-ms-lineendings.c" 2
|
||||
// RUN: %clang_cc1 %s -E -o - -I %S/Inputs -isystem %S/Inputs/SystemHeaderPrefix | FileCheck %s
|
||||
#include <noline.h>
|
||||
#include <line-directive-in-system.h>
|
||||
|
||||
#include "line-directive.h"
|
||||
|
||||
// This tests that the line numbers for the current file are correctly outputted
|
||||
// for the include-file-completed test case. This file should be CRLF.
|
||||
|
||||
// CHECK: # 1 "{{.*}}system-header-line-directive-ms-lineendings.c" 2
|
||||
// CHECK: # 1 "{{.*}}noline.h" 1 3
|
||||
// CHECK: foo(void);
|
||||
// CHECK: # 3 "{{.*}}system-header-line-directive-ms-lineendings.c" 2
|
||||
// CHECK: # 1 "{{.*}}line-directive-in-system.h" 1 3
|
||||
// The "3" below indicates that "foo.h" is considered a system header.
|
||||
// CHECK: # 1 "foo.h" 3
|
||||
// CHECK: foo(void);
|
||||
// CHECK: # 4 "{{.*}}system-header-line-directive-ms-lineendings.c" 2
|
||||
// CHECK: # 1 "{{.*}}line-directive.h" 1
|
||||
// CHECK: # 10 "foo.h"{{$}}
|
||||
// CHECK: # 6 "{{.*}}system-header-line-directive-ms-lineendings.c" 2
|
||||
|
@ -1,31 +1,31 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -ast-dump -x hlsl -o - %s | FileCheck %s
|
||||
|
||||
|
||||
struct MyBitFields {
|
||||
// CHECK: FieldDecl 0x{{[0-9a-f]+}} <line:9:3, col:25> col:16 referenced field1 'unsigned int'
|
||||
// CHECK:-ConstantExpr 0x{{[0-9a-f]+}} <col:25> 'int'
|
||||
// CHECK:-value: Int 3
|
||||
// CHECK:-IntegerLiteral 0x{{[0-9a-f]+}} <col:25> 'int' 3
|
||||
unsigned int field1 : 3; // 3 bits for field1
|
||||
|
||||
// CHECK:FieldDecl 0x{{[0-9a-f]+}} <line:15:3, col:25> col:16 referenced field2 'unsigned int'
|
||||
// CHECK:-ConstantExpr 0x{{[0-9a-f]+}} <col:25> 'int'
|
||||
// CHECK:-value: Int 4
|
||||
// CHECK:-IntegerLiteral 0x{{[0-9a-f]+}} <col:25> 'int' 4
|
||||
unsigned int field2 : 4; // 4 bits for field2
|
||||
|
||||
// CHECK:FieldDecl 0x{{[0-9a-f]+}} <line:21:3, col:16> col:7 field3 'int'
|
||||
// CHECK:-ConstantExpr 0x{{[0-9a-f]+}} <col:16> 'int'
|
||||
// CHECK:-value: Int 5
|
||||
// CHECK:-IntegerLiteral 0x{{[0-9a-f]+}} <col:16> 'int' 5
|
||||
int field3 : 5; // 5 bits for field3 (signed)
|
||||
};
|
||||
|
||||
|
||||
|
||||
[numthreads(1,1,1)]
|
||||
void main() {
|
||||
MyBitFields m;
|
||||
m.field1 = 4;
|
||||
m.field2 = m.field1*2;
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -ast-dump -x hlsl -o - %s | FileCheck %s
|
||||
|
||||
|
||||
struct MyBitFields {
|
||||
// CHECK: FieldDecl 0x{{[0-9a-f]+}} <line:9:3, col:25> col:16 referenced field1 'unsigned int'
|
||||
// CHECK:-ConstantExpr 0x{{[0-9a-f]+}} <col:25> 'int'
|
||||
// CHECK:-value: Int 3
|
||||
// CHECK:-IntegerLiteral 0x{{[0-9a-f]+}} <col:25> 'int' 3
|
||||
unsigned int field1 : 3; // 3 bits for field1
|
||||
|
||||
// CHECK:FieldDecl 0x{{[0-9a-f]+}} <line:15:3, col:25> col:16 referenced field2 'unsigned int'
|
||||
// CHECK:-ConstantExpr 0x{{[0-9a-f]+}} <col:25> 'int'
|
||||
// CHECK:-value: Int 4
|
||||
// CHECK:-IntegerLiteral 0x{{[0-9a-f]+}} <col:25> 'int' 4
|
||||
unsigned int field2 : 4; // 4 bits for field2
|
||||
|
||||
// CHECK:FieldDecl 0x{{[0-9a-f]+}} <line:21:3, col:16> col:7 field3 'int'
|
||||
// CHECK:-ConstantExpr 0x{{[0-9a-f]+}} <col:16> 'int'
|
||||
// CHECK:-value: Int 5
|
||||
// CHECK:-IntegerLiteral 0x{{[0-9a-f]+}} <col:16> 'int' 5
|
||||
int field3 : 5; // 5 bits for field3 (signed)
|
||||
};
|
||||
|
||||
|
||||
|
||||
[numthreads(1,1,1)]
|
||||
void main() {
|
||||
MyBitFields m;
|
||||
m.field1 = 4;
|
||||
m.field2 = m.field1*2;
|
||||
}
|
@ -1,21 +1,21 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s
|
||||
|
||||
// tests that hlsl annotations are properly parsed when applied on field decls,
|
||||
// and that the annotation gets properly placed on the AST.
|
||||
|
||||
struct Eg9{
|
||||
// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} <col:1, col:8> col:8 implicit struct Eg9
|
||||
// CHECK: FieldDecl 0x{{[0-9a-f]+}} <line:10:3, col:16> col:16 referenced a 'unsigned int'
|
||||
// CHECK: -HLSLSV_DispatchThreadIDAttr 0x{{[0-9a-f]+}} <col:20>
|
||||
unsigned int a : SV_DispatchThreadID;
|
||||
};
|
||||
Eg9 e9;
|
||||
|
||||
|
||||
RWBuffer<int> In : register(u1);
|
||||
|
||||
|
||||
[numthreads(1,1,1)]
|
||||
void main() {
|
||||
In[0] = e9.a;
|
||||
}
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s
|
||||
|
||||
// tests that hlsl annotations are properly parsed when applied on field decls,
|
||||
// and that the annotation gets properly placed on the AST.
|
||||
|
||||
struct Eg9{
|
||||
// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} <col:1, col:8> col:8 implicit struct Eg9
|
||||
// CHECK: FieldDecl 0x{{[0-9a-f]+}} <line:10:3, col:16> col:16 referenced a 'unsigned int'
|
||||
// CHECK: -HLSLSV_DispatchThreadIDAttr 0x{{[0-9a-f]+}} <col:20>
|
||||
unsigned int a : SV_DispatchThreadID;
|
||||
};
|
||||
Eg9 e9;
|
||||
|
||||
|
||||
RWBuffer<int> In : register(u1);
|
||||
|
||||
|
||||
[numthreads(1,1,1)]
|
||||
void main() {
|
||||
In[0] = e9.a;
|
||||
}
|
||||
|
@ -1,25 +1,25 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -x hlsl -ast-dump -o - %s | FileCheck %s
|
||||
|
||||
typedef vector<float, 4> float4;
|
||||
|
||||
// CHECK: -TypeAliasDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 4]]:1, col:83>
|
||||
// CHECK: -HLSLAttributedResourceType 0x{{[0-9a-f]+}} '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(int)]]
|
||||
using ResourceIntAliasT = __hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(int)]];
|
||||
ResourceIntAliasT h1;
|
||||
|
||||
// CHECK: -VarDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 3]]:1, col:82> col:82 h2 '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(float4)]]
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(float4)]] h2;
|
||||
|
||||
// CHECK: ClassTemplateDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 6]]:1, line:[[# @LINE + 8]]:1> line:[[# @LINE + 6]]:30 S
|
||||
// CHECK: TemplateTypeParmDecl 0x{{[0-9a-f]+}} <col:11, col:20> col:20 referenced typename depth 0 index 0 T
|
||||
// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} <col:23, line:[[# @LINE + 6]]:1> line:[[# @LINE + 4]]:30 struct S definition
|
||||
// CHECK: FieldDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 4]]:3, col:79> col:79 h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(T)]]
|
||||
template <typename T> struct S {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(T)]] h;
|
||||
};
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -x hlsl -ast-dump -o - %s | FileCheck %s
|
||||
|
||||
typedef vector<float, 4> float4;
|
||||
|
||||
// CHECK: -TypeAliasDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 4]]:1, col:83>
|
||||
// CHECK: -HLSLAttributedResourceType 0x{{[0-9a-f]+}} '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(int)]]
|
||||
using ResourceIntAliasT = __hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(int)]];
|
||||
ResourceIntAliasT h1;
|
||||
|
||||
// CHECK: -VarDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 3]]:1, col:82> col:82 h2 '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(float4)]]
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(float4)]] h2;
|
||||
|
||||
// CHECK: ClassTemplateDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 6]]:1, line:[[# @LINE + 8]]:1> line:[[# @LINE + 6]]:30 S
|
||||
// CHECK: TemplateTypeParmDecl 0x{{[0-9a-f]+}} <col:11, col:20> col:20 referenced typename depth 0 index 0 T
|
||||
// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} <col:23, line:[[# @LINE + 6]]:1> line:[[# @LINE + 4]]:30 struct S definition
|
||||
// CHECK: FieldDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 4]]:3, col:79> col:79 h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(T)]]
|
||||
template <typename T> struct S {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(T)]] h;
|
||||
};
|
||||
|
@ -1,28 +1,28 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -x hlsl -o - %s -verify
|
||||
|
||||
typedef vector<float, 4> float4;
|
||||
|
||||
// expected-error@+1{{'contained_type' attribute cannot be applied to a declaration}}
|
||||
[[hlsl::contained_type(float4)]] __hlsl_resource_t h1;
|
||||
|
||||
// expected-error@+1{{'contained_type' attribute takes one argument}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type()]] h3;
|
||||
|
||||
// expected-error@+1{{expected a type}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(0)]] h4;
|
||||
|
||||
// expected-error@+1{{unknown type name 'a'}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(a)]] h5;
|
||||
|
||||
// expected-error@+1{{expected a type}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type("b", c)]] h6;
|
||||
|
||||
// expected-warning@+1{{attribute 'contained_type' is already applied}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(float)]] [[hlsl::contained_type(float)]] h7;
|
||||
|
||||
// expected-warning@+1{{attribute 'contained_type' is already applied with different arguments}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(float)]] [[hlsl::contained_type(int)]] h8;
|
||||
|
||||
// expected-error@+2{{attribute 'resource_class' can be used only on HLSL intangible type '__hlsl_resource_t'}}
|
||||
// expected-error@+1{{attribute 'contained_type' can be used only on HLSL intangible type '__hlsl_resource_t'}}
|
||||
float [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(float)]] res5;
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -std=hlsl202x -x hlsl -o - %s -verify
|
||||
|
||||
typedef vector<float, 4> float4;
|
||||
|
||||
// expected-error@+1{{'contained_type' attribute cannot be applied to a declaration}}
|
||||
[[hlsl::contained_type(float4)]] __hlsl_resource_t h1;
|
||||
|
||||
// expected-error@+1{{'contained_type' attribute takes one argument}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type()]] h3;
|
||||
|
||||
// expected-error@+1{{expected a type}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(0)]] h4;
|
||||
|
||||
// expected-error@+1{{unknown type name 'a'}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(a)]] h5;
|
||||
|
||||
// expected-error@+1{{expected a type}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type("b", c)]] h6;
|
||||
|
||||
// expected-warning@+1{{attribute 'contained_type' is already applied}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(float)]] [[hlsl::contained_type(float)]] h7;
|
||||
|
||||
// expected-warning@+1{{attribute 'contained_type' is already applied with different arguments}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(float)]] [[hlsl::contained_type(int)]] h8;
|
||||
|
||||
// expected-error@+2{{attribute 'resource_class' can be used only on HLSL intangible type '__hlsl_resource_t'}}
|
||||
// expected-error@+1{{attribute 'contained_type' can be used only on HLSL intangible type '__hlsl_resource_t'}}
|
||||
float [[hlsl::resource_class(UAV)]] [[hlsl::contained_type(float)]] res5;
|
||||
|
@ -1,22 +1,22 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s
|
||||
|
||||
// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} struct MyBuffer definition
|
||||
// CHECK: FieldDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 4]]:3, col:68> col:68 h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::is_rov]]
|
||||
struct MyBuffer {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::is_rov]] h;
|
||||
};
|
||||
|
||||
// CHECK: VarDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 3]]:1, col:66> col:66 res '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::is_rov]]
|
||||
__hlsl_resource_t [[hlsl::is_rov]] [[hlsl::resource_class(SRV)]] res;
|
||||
|
||||
// CHECK: FunctionDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 4]]:1, line:[[# @LINE + 6]]:1> line:[[# @LINE + 4]]:6 f 'void ()
|
||||
// CHECK: VarDecl 0x{{[0-9a-f]+}} <col:3, col:72> col:72 r '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::is_rov]]
|
||||
void f() {
|
||||
__hlsl_resource_t [[hlsl::resource_class(Sampler)]] [[hlsl::is_rov]] r;
|
||||
}
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s
|
||||
|
||||
// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} struct MyBuffer definition
|
||||
// CHECK: FieldDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 4]]:3, col:68> col:68 h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::is_rov]]
|
||||
struct MyBuffer {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::is_rov]] h;
|
||||
};
|
||||
|
||||
// CHECK: VarDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 3]]:1, col:66> col:66 res '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::is_rov]]
|
||||
__hlsl_resource_t [[hlsl::is_rov]] [[hlsl::resource_class(SRV)]] res;
|
||||
|
||||
// CHECK: FunctionDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 4]]:1, line:[[# @LINE + 6]]:1> line:[[# @LINE + 4]]:6 f 'void ()
|
||||
// CHECK: VarDecl 0x{{[0-9a-f]+}} <col:3, col:72> col:72 r '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::is_rov]]
|
||||
void f() {
|
||||
__hlsl_resource_t [[hlsl::resource_class(Sampler)]] [[hlsl::is_rov]] r;
|
||||
}
|
||||
|
@ -1,20 +1,20 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -o - %s -verify
|
||||
|
||||
// expected-error@+1{{'is_rov' attribute cannot be applied to a declaration}}
|
||||
[[hlsl::is_rov]] __hlsl_resource_t res0;
|
||||
|
||||
// expected-error@+1{{HLSL resource needs to have [[hlsl::resource_class()]] attribute}}
|
||||
__hlsl_resource_t [[hlsl::is_rov]] res1;
|
||||
|
||||
// expected-error@+1{{'is_rov' attribute takes no arguments}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::is_rov(3)]] res2;
|
||||
|
||||
// expected-error@+1{{use of undeclared identifier 'gibberish'}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::is_rov(gibberish)]] res3;
|
||||
|
||||
// expected-warning@+1{{attribute 'is_rov' is already applied}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::is_rov]] [[hlsl::is_rov]] res4;
|
||||
|
||||
// expected-error@+2{{attribute 'resource_class' can be used only on HLSL intangible type '__hlsl_resource_t'}}
|
||||
// expected-error@+1{{attribute 'is_rov' can be used only on HLSL intangible type '__hlsl_resource_t'}}
|
||||
float [[hlsl::resource_class(UAV)]] [[hlsl::is_rov]] res5;
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -o - %s -verify
|
||||
|
||||
// expected-error@+1{{'is_rov' attribute cannot be applied to a declaration}}
|
||||
[[hlsl::is_rov]] __hlsl_resource_t res0;
|
||||
|
||||
// expected-error@+1{{HLSL resource needs to have [[hlsl::resource_class()]] attribute}}
|
||||
__hlsl_resource_t [[hlsl::is_rov]] res1;
|
||||
|
||||
// expected-error@+1{{'is_rov' attribute takes no arguments}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::is_rov(3)]] res2;
|
||||
|
||||
// expected-error@+1{{use of undeclared identifier 'gibberish'}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::is_rov(gibberish)]] res3;
|
||||
|
||||
// expected-warning@+1{{attribute 'is_rov' is already applied}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::is_rov]] [[hlsl::is_rov]] res4;
|
||||
|
||||
// expected-error@+2{{attribute 'resource_class' can be used only on HLSL intangible type '__hlsl_resource_t'}}
|
||||
// expected-error@+1{{attribute 'is_rov' can be used only on HLSL intangible type '__hlsl_resource_t'}}
|
||||
float [[hlsl::resource_class(UAV)]] [[hlsl::is_rov]] res5;
|
||||
|
@ -1,22 +1,22 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s
|
||||
|
||||
// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} struct MyBuffer definition
|
||||
// CHECK: FieldDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 4]]:3, col:72> col:72 h1 '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
|
||||
struct MyBuffer {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer]] h1;
|
||||
};
|
||||
|
||||
// CHECK: VarDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 3]]:1, col:70> col:70 h2 '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
|
||||
__hlsl_resource_t [[hlsl::raw_buffer]] [[hlsl::resource_class(SRV)]] h2;
|
||||
|
||||
// CHECK: FunctionDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 4]]:1, line:[[# @LINE + 6]]:1> line:[[# @LINE + 4]]:6 f 'void ()
|
||||
// CHECK: VarDecl 0x{{[0-9a-f]+}} <col:3, col:72> col:72 h3 '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
|
||||
void f() {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer]] h3;
|
||||
}
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s
|
||||
|
||||
// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} struct MyBuffer definition
|
||||
// CHECK: FieldDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 4]]:3, col:72> col:72 h1 '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
|
||||
struct MyBuffer {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer]] h1;
|
||||
};
|
||||
|
||||
// CHECK: VarDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 3]]:1, col:70> col:70 h2 '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
|
||||
__hlsl_resource_t [[hlsl::raw_buffer]] [[hlsl::resource_class(SRV)]] h2;
|
||||
|
||||
// CHECK: FunctionDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 4]]:1, line:[[# @LINE + 6]]:1> line:[[# @LINE + 4]]:6 f 'void ()
|
||||
// CHECK: VarDecl 0x{{[0-9a-f]+}} <col:3, col:72> col:72 h3 '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::raw_buffer]]
|
||||
void f() {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer]] h3;
|
||||
}
|
||||
|
@ -1,17 +1,17 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -o - %s -verify
|
||||
|
||||
// expected-error@+1{{'raw_buffer' attribute cannot be applied to a declaration}}
|
||||
[[hlsl::raw_buffer]] __hlsl_resource_t res0;
|
||||
|
||||
// expected-error@+1{{'raw_buffer' attribute takes no arguments}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer(3)]] res2;
|
||||
|
||||
// expected-error@+1{{use of undeclared identifier 'gibberish'}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer(gibberish)]] res3;
|
||||
|
||||
// expected-warning@+1{{attribute 'raw_buffer' is already applied}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer]] [[hlsl::raw_buffer]] res4;
|
||||
|
||||
// expected-error@+2{{attribute 'resource_class' can be used only on HLSL intangible type '__hlsl_resource_t'}}
|
||||
// expected-error@+1{{attribute 'raw_buffer' can be used only on HLSL intangible type '__hlsl_resource_t'}}
|
||||
float [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer]] res5;
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -o - %s -verify
|
||||
|
||||
// expected-error@+1{{'raw_buffer' attribute cannot be applied to a declaration}}
|
||||
[[hlsl::raw_buffer]] __hlsl_resource_t res0;
|
||||
|
||||
// expected-error@+1{{'raw_buffer' attribute takes no arguments}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer(3)]] res2;
|
||||
|
||||
// expected-error@+1{{use of undeclared identifier 'gibberish'}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer(gibberish)]] res3;
|
||||
|
||||
// expected-warning@+1{{attribute 'raw_buffer' is already applied}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer]] [[hlsl::raw_buffer]] res4;
|
||||
|
||||
// expected-error@+2{{attribute 'resource_class' can be used only on HLSL intangible type '__hlsl_resource_t'}}
|
||||
// expected-error@+1{{attribute 'raw_buffer' can be used only on HLSL intangible type '__hlsl_resource_t'}}
|
||||
float [[hlsl::resource_class(UAV)]] [[hlsl::raw_buffer]] res5;
|
||||
|
@ -1,37 +1,37 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s
|
||||
|
||||
// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} struct MyBuffer definition
|
||||
// CHECK: FieldDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 3]]:3, col:51> col:51 h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
struct MyBuffer {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] h;
|
||||
};
|
||||
|
||||
// CHECK: VarDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 2]]:1, col:49> col:49 res '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
|
||||
__hlsl_resource_t [[hlsl::resource_class(SRV)]] res;
|
||||
|
||||
// CHECK: FunctionDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 3]]:1, line:[[# @LINE + 5]]:1> line:[[# @LINE + 3]]:6 f 'void ()
|
||||
// CHECK: VarDecl 0x{{[0-9a-f]+}} <col:3, col:55> col:55 r '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
|
||||
void f() {
|
||||
__hlsl_resource_t [[hlsl::resource_class(Sampler)]] r;
|
||||
}
|
||||
|
||||
// CHECK: ClassTemplateDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 6]]:1, line:[[# @LINE + 8]]:1> line:[[# @LINE + 6]]:29 MyBuffer2
|
||||
// CHECK: TemplateTypeParmDecl 0x{{[0-9a-f]+}} <col:10, col:19> col:19 typename depth 0 index 0 T
|
||||
// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} <col:22, line:[[# @LINE + 6]]:1> line:[[# @LINE + 4]]:29 struct MyBuffer2 definition
|
||||
// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} <col:22, col:29> col:29 implicit struct MyBuffer2
|
||||
// CHECK: FieldDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 3]]:3, col:51> col:51 h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
template<typename T> struct MyBuffer2 {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] h;
|
||||
};
|
||||
|
||||
// CHECK: ClassTemplateSpecializationDecl 0x{{[0-9a-f]+}} <line:[[# @LINE - 4]]:1, line:[[# @LINE - 2]]:1> line:[[# @LINE - 4]]:29 struct MyBuffer2 definition implicit_instantiation
|
||||
// CHECK: TemplateArgument type 'float'
|
||||
// CHECK: BuiltinType 0x{{[0-9a-f]+}} 'float'
|
||||
// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} <col:22, col:29> col:29 implicit struct MyBuffer2
|
||||
// CHECK: FieldDecl 0x{{[0-9a-f]+}} <line:[[# @LINE - 7]]:3, col:51> col:51 h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
MyBuffer2<float> myBuffer2;
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s
|
||||
|
||||
// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} struct MyBuffer definition
|
||||
// CHECK: FieldDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 3]]:3, col:51> col:51 h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
struct MyBuffer {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] h;
|
||||
};
|
||||
|
||||
// CHECK: VarDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 2]]:1, col:49> col:49 res '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]
|
||||
__hlsl_resource_t [[hlsl::resource_class(SRV)]] res;
|
||||
|
||||
// CHECK: FunctionDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 3]]:1, line:[[# @LINE + 5]]:1> line:[[# @LINE + 3]]:6 f 'void ()
|
||||
// CHECK: VarDecl 0x{{[0-9a-f]+}} <col:3, col:55> col:55 r '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(Sampler)]]
|
||||
void f() {
|
||||
__hlsl_resource_t [[hlsl::resource_class(Sampler)]] r;
|
||||
}
|
||||
|
||||
// CHECK: ClassTemplateDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 6]]:1, line:[[# @LINE + 8]]:1> line:[[# @LINE + 6]]:29 MyBuffer2
|
||||
// CHECK: TemplateTypeParmDecl 0x{{[0-9a-f]+}} <col:10, col:19> col:19 typename depth 0 index 0 T
|
||||
// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} <col:22, line:[[# @LINE + 6]]:1> line:[[# @LINE + 4]]:29 struct MyBuffer2 definition
|
||||
// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} <col:22, col:29> col:29 implicit struct MyBuffer2
|
||||
// CHECK: FieldDecl 0x{{[0-9a-f]+}} <line:[[# @LINE + 3]]:3, col:51> col:51 h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
template<typename T> struct MyBuffer2 {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] h;
|
||||
};
|
||||
|
||||
// CHECK: ClassTemplateSpecializationDecl 0x{{[0-9a-f]+}} <line:[[# @LINE - 4]]:1, line:[[# @LINE - 2]]:1> line:[[# @LINE - 4]]:29 struct MyBuffer2 definition implicit_instantiation
|
||||
// CHECK: TemplateArgument type 'float'
|
||||
// CHECK: BuiltinType 0x{{[0-9a-f]+}} 'float'
|
||||
// CHECK: CXXRecordDecl 0x{{[0-9a-f]+}} <col:22, col:29> col:29 implicit struct MyBuffer2
|
||||
// CHECK: FieldDecl 0x{{[0-9a-f]+}} <line:[[# @LINE - 7]]:3, col:51> col:51 h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
MyBuffer2<float> myBuffer2;
|
||||
|
@ -1,22 +1,22 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -o - %s -verify
|
||||
|
||||
// expected-error@+1{{'resource_class' attribute cannot be applied to a declaration}}
|
||||
[[hlsl::resource_class(UAV)]] __hlsl_resource_t e0;
|
||||
|
||||
// expected-error@+1{{'resource_class' attribute takes one argument}}
|
||||
__hlsl_resource_t [[hlsl::resource_class()]] e1;
|
||||
|
||||
// expected-warning@+1{{ResourceClass attribute argument not supported: gibberish}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(gibberish)]] e2;
|
||||
|
||||
// expected-warning@+1{{attribute 'resource_class' is already applied with different arguments}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(SRV)]] [[hlsl::resource_class(UAV)]] e3;
|
||||
|
||||
// expected-warning@+1{{attribute 'resource_class' is already applied}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(SRV)]] [[hlsl::resource_class(SRV)]] e4;
|
||||
|
||||
// expected-error@+1{{'resource_class' attribute takes one argument}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(SRV, "aa")]] e5;
|
||||
|
||||
// expected-error@+1{{attribute 'resource_class' can be used only on HLSL intangible type '__hlsl_resource_t'}}
|
||||
float [[hlsl::resource_class(UAV)]] e6;
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -o - %s -verify
|
||||
|
||||
// expected-error@+1{{'resource_class' attribute cannot be applied to a declaration}}
|
||||
[[hlsl::resource_class(UAV)]] __hlsl_resource_t e0;
|
||||
|
||||
// expected-error@+1{{'resource_class' attribute takes one argument}}
|
||||
__hlsl_resource_t [[hlsl::resource_class()]] e1;
|
||||
|
||||
// expected-warning@+1{{ResourceClass attribute argument not supported: gibberish}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(gibberish)]] e2;
|
||||
|
||||
// expected-warning@+1{{attribute 'resource_class' is already applied with different arguments}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(SRV)]] [[hlsl::resource_class(UAV)]] e3;
|
||||
|
||||
// expected-warning@+1{{attribute 'resource_class' is already applied}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(SRV)]] [[hlsl::resource_class(SRV)]] e4;
|
||||
|
||||
// expected-error@+1{{'resource_class' attribute takes one argument}}
|
||||
__hlsl_resource_t [[hlsl::resource_class(SRV, "aa")]] e5;
|
||||
|
||||
// expected-error@+1{{attribute 'resource_class' can be used only on HLSL intangible type '__hlsl_resource_t'}}
|
||||
float [[hlsl::resource_class(UAV)]] e6;
|
||||
|
@ -1,21 +1,21 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -ast-dump -o - %s | FileCheck %s
|
||||
|
||||
// CHECK: -ClassTemplateSpecializationDecl 0x{{[0-9a-f]+}} <<invalid sloc>> <invalid sloc> class RWBuffer definition implicit_instantiation
|
||||
// CHECK: -TemplateArgument type 'float'
|
||||
// CHECK: `-BuiltinType 0x{{[0-9a-f]+}} 'float'
|
||||
// CHECK: -FieldDecl 0x{{[0-9a-f]+}} <<invalid sloc>> <invalid sloc> implicit h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(float)]]
|
||||
// CHECK: -HLSLResourceAttr 0x{{[0-9a-f]+}} <<invalid sloc>> Implicit TypedBuffer
|
||||
RWBuffer<float> Buffer1;
|
||||
|
||||
// CHECK: -ClassTemplateSpecializationDecl 0x{{[0-9a-f]+}} <<invalid sloc>> <invalid sloc> class RasterizerOrderedBuffer definition implicit_instantiation
|
||||
// CHECK: -TemplateArgument type 'vector<float, 4>'
|
||||
// CHECK: `-ExtVectorType 0x{{[0-9a-f]+}} 'vector<float, 4>' 4
|
||||
// CHECK: `-BuiltinType 0x{{[0-9a-f]+}} 'float'
|
||||
// CHECK: -FieldDecl 0x{{[0-9a-f]+}} <<invalid sloc>> <invalid sloc> implicit h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::is_rov]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<float, 4>)]]
|
||||
// CHECK: -HLSLResourceAttr 0x{{[0-9a-f]+}} <<invalid sloc>> Implicit TypedBuffer
|
||||
RasterizerOrderedBuffer<vector<float, 4> > BufferArray3[4];
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -ast-dump -o - %s | FileCheck %s
|
||||
|
||||
// CHECK: -ClassTemplateSpecializationDecl 0x{{[0-9a-f]+}} <<invalid sloc>> <invalid sloc> class RWBuffer definition implicit_instantiation
|
||||
// CHECK: -TemplateArgument type 'float'
|
||||
// CHECK: `-BuiltinType 0x{{[0-9a-f]+}} 'float'
|
||||
// CHECK: -FieldDecl 0x{{[0-9a-f]+}} <<invalid sloc>> <invalid sloc> implicit h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(float)]]
|
||||
// CHECK: -HLSLResourceAttr 0x{{[0-9a-f]+}} <<invalid sloc>> Implicit TypedBuffer
|
||||
RWBuffer<float> Buffer1;
|
||||
|
||||
// CHECK: -ClassTemplateSpecializationDecl 0x{{[0-9a-f]+}} <<invalid sloc>> <invalid sloc> class RasterizerOrderedBuffer definition implicit_instantiation
|
||||
// CHECK: -TemplateArgument type 'vector<float, 4>'
|
||||
// CHECK: `-ExtVectorType 0x{{[0-9a-f]+}} 'vector<float, 4>' 4
|
||||
// CHECK: `-BuiltinType 0x{{[0-9a-f]+}} 'float'
|
||||
// CHECK: -FieldDecl 0x{{[0-9a-f]+}} <<invalid sloc>> <invalid sloc> implicit h '__hlsl_resource_t
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::resource_class(UAV)]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::is_rov]]
|
||||
// CHECK-SAME{LITERAL}: [[hlsl::contained_type(vector<float, 4>)]]
|
||||
// CHECK: -HLSLResourceAttr 0x{{[0-9a-f]+}} <<invalid sloc>> Implicit TypedBuffer
|
||||
RasterizerOrderedBuffer<vector<float, 4> > BufferArray3[4];
|
||||
|
@ -1,65 +1,65 @@
|
||||
// RUN: %clang_cc1 -triple aarch64 -target-feature +sve \
|
||||
// RUN: -disable-O0-optnone -o - -fsyntax-only %s -verify
|
||||
// REQUIRES: aarch64-registered-target
|
||||
|
||||
#include <arm_sve.h>
|
||||
|
||||
svfloat32_t test_asin_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_asin(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_acos_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_acos(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_atan_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_atan(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_atan2_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_atan2(v, v);
|
||||
// expected-error@-1 {{1st argument must be a floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_sin_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_sin(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_cos_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_cos(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_tan_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_tan(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_sinh_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_sinh(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_cosh_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_cosh(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_tanh_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_tanh(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
// RUN: %clang_cc1 -triple aarch64 -target-feature +sve \
|
||||
// RUN: -disable-O0-optnone -o - -fsyntax-only %s -verify
|
||||
// REQUIRES: aarch64-registered-target
|
||||
|
||||
#include <arm_sve.h>
|
||||
|
||||
svfloat32_t test_asin_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_asin(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_acos_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_acos(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_atan_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_atan(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_atan2_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_atan2(v, v);
|
||||
// expected-error@-1 {{1st argument must be a floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_sin_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_sin(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_cos_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_cos(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_tan_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_tan(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_sinh_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_sinh(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_cosh_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_cosh(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
svfloat32_t test_tanh_vv_i8mf8(svfloat32_t v) {
|
||||
|
||||
return __builtin_elementwise_tanh(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
@ -1,67 +1,67 @@
|
||||
// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d \
|
||||
// RUN: -target-feature +v -target-feature +zfh -target-feature +zvfh \
|
||||
// RUN: -disable-O0-optnone -o - -fsyntax-only %s -verify
|
||||
// REQUIRES: riscv-registered-target
|
||||
|
||||
#include <riscv_vector.h>
|
||||
|
||||
vfloat32mf2_t test_asin_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_asin(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_acos_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_acos(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_atan_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_atan(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_atan2_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_atan2(v, v);
|
||||
// expected-error@-1 {{1st argument must be a floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_sin_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_sin(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_cos_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_cos(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_tan_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_tan(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_sinh_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_sinh(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_cosh_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_cosh(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_tanh_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_tanh(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d \
|
||||
// RUN: -target-feature +v -target-feature +zfh -target-feature +zvfh \
|
||||
// RUN: -disable-O0-optnone -o - -fsyntax-only %s -verify
|
||||
// REQUIRES: riscv-registered-target
|
||||
|
||||
#include <riscv_vector.h>
|
||||
|
||||
vfloat32mf2_t test_asin_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_asin(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_acos_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_acos(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_atan_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_atan(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_atan2_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_atan2(v, v);
|
||||
// expected-error@-1 {{1st argument must be a floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_sin_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_sin(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_cos_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_cos(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_tan_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_tan(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_sinh_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_sinh(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_cosh_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_cosh(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
vfloat32mf2_t test_tanh_vv_i8mf8(vfloat32mf2_t v) {
|
||||
|
||||
return __builtin_elementwise_tanh(v);
|
||||
// expected-error@-1 {{1st argument must be a vector, integer or floating point type}}
|
||||
}
|
||||
|
||||
|
@ -1,119 +1,119 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute \
|
||||
// RUN: -fsyntax-only -verify %s
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.5)))
|
||||
float fx(float); // #fx
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.6)))
|
||||
half fx(half); // #fx_half
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
|
||||
float fy(float); // #fy
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh)))
|
||||
float fz(float); // #fz
|
||||
|
||||
float also_alive(float f) {
|
||||
// expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #also_alive_fx_call
|
||||
// expected-error@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #also_alive_fy_call
|
||||
// expected-error@#also_alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #also_alive_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
float alive(float f) {
|
||||
// expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #alive_fx_call
|
||||
// expected-error@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #alive_fy_call
|
||||
// expected-error@#alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #alive_fz_call
|
||||
|
||||
return also_alive(f);
|
||||
}
|
||||
|
||||
float also_dead(float f) {
|
||||
// unreachable code - no errors expected
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float dead(float f) {
|
||||
// unreachable code - no errors expected
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
|
||||
return also_dead(f);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T aliveTemp(T f) {
|
||||
// expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #aliveTemp_fx_call
|
||||
// expected-error@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #aliveTemp_fy_call
|
||||
// expected-error@#aliveTemp_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #aliveTemp_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T> T aliveTemp2(T f) {
|
||||
// expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}}
|
||||
// expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}}
|
||||
// expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
return fx(f); // #aliveTemp2_fx_call
|
||||
}
|
||||
|
||||
half test(half x) {
|
||||
return aliveTemp2(x);
|
||||
}
|
||||
|
||||
float test(float x) {
|
||||
return aliveTemp2(x);
|
||||
}
|
||||
|
||||
class MyClass
|
||||
{
|
||||
float F;
|
||||
float makeF() {
|
||||
// expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(F); // #MyClass_makeF_fx_call
|
||||
// expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(F); // #MyClass_makeF_fy_call
|
||||
// expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(F); // #MyClass_makeF_fz_call
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
[numthreads(4,1,1)]
|
||||
float main() {
|
||||
float f = 3;
|
||||
MyClass C = { 1.0f };
|
||||
float a = alive(f);
|
||||
float b = aliveTemp<float>(f); // #aliveTemp_inst
|
||||
float c = C.makeF();
|
||||
float d = test((float)1.0);
|
||||
float e = test((half)1.0);
|
||||
return a * b * c;
|
||||
}
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute \
|
||||
// RUN: -fsyntax-only -verify %s
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.5)))
|
||||
float fx(float); // #fx
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.6)))
|
||||
half fx(half); // #fx_half
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
|
||||
float fy(float); // #fy
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh)))
|
||||
float fz(float); // #fz
|
||||
|
||||
float also_alive(float f) {
|
||||
// expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #also_alive_fx_call
|
||||
// expected-error@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #also_alive_fy_call
|
||||
// expected-error@#also_alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #also_alive_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
float alive(float f) {
|
||||
// expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #alive_fx_call
|
||||
// expected-error@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #alive_fy_call
|
||||
// expected-error@#alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #alive_fz_call
|
||||
|
||||
return also_alive(f);
|
||||
}
|
||||
|
||||
float also_dead(float f) {
|
||||
// unreachable code - no errors expected
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float dead(float f) {
|
||||
// unreachable code - no errors expected
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
|
||||
return also_dead(f);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T aliveTemp(T f) {
|
||||
// expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #aliveTemp_fx_call
|
||||
// expected-error@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #aliveTemp_fy_call
|
||||
// expected-error@#aliveTemp_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #aliveTemp_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T> T aliveTemp2(T f) {
|
||||
// expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}}
|
||||
// expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}}
|
||||
// expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
return fx(f); // #aliveTemp2_fx_call
|
||||
}
|
||||
|
||||
half test(half x) {
|
||||
return aliveTemp2(x);
|
||||
}
|
||||
|
||||
float test(float x) {
|
||||
return aliveTemp2(x);
|
||||
}
|
||||
|
||||
class MyClass
|
||||
{
|
||||
float F;
|
||||
float makeF() {
|
||||
// expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(F); // #MyClass_makeF_fx_call
|
||||
// expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(F); // #MyClass_makeF_fy_call
|
||||
// expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(F); // #MyClass_makeF_fz_call
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
[numthreads(4,1,1)]
|
||||
float main() {
|
||||
float f = 3;
|
||||
MyClass C = { 1.0f };
|
||||
float a = alive(f);
|
||||
float b = aliveTemp<float>(f); // #aliveTemp_inst
|
||||
float c = C.makeF();
|
||||
float d = test((float)1.0);
|
||||
float e = test((half)1.0);
|
||||
return a * b * c;
|
||||
}
|
||||
|
@ -1,180 +1,180 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \
|
||||
// RUN: -fsyntax-only -verify %s
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.5)))
|
||||
float fx(float); // #fx
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.6)))
|
||||
half fx(half); // #fx_half
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
|
||||
float fy(float); // #fy
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh)))
|
||||
float fz(float); // #fz
|
||||
|
||||
float also_alive(float f) {
|
||||
// expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #also_alive_fx_call
|
||||
|
||||
// expected-error@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #also_alive_fy_call
|
||||
|
||||
// expected-error@#also_alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #also_alive_fz_call
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float alive(float f) {
|
||||
// expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #alive_fx_call
|
||||
|
||||
// expected-error@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #alive_fy_call
|
||||
|
||||
// expected-error@#alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #alive_fz_call
|
||||
|
||||
return also_alive(f);
|
||||
}
|
||||
|
||||
float also_dead(float f) {
|
||||
// unreachable code - no errors expected
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float dead(float f) {
|
||||
// unreachable code - no errors expected
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
return also_dead(f);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T aliveTemp(T f) {
|
||||
// expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #aliveTemp_fx_call
|
||||
// expected-error@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #aliveTemp_fy_call
|
||||
// expected-error@#aliveTemp_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #aliveTemp_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T> T aliveTemp2(T f) {
|
||||
// expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}}
|
||||
// expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}}
|
||||
// expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
return fx(f); // #aliveTemp2_fx_call
|
||||
}
|
||||
|
||||
half test(half x) {
|
||||
return aliveTemp2(x);
|
||||
}
|
||||
|
||||
float test(float x) {
|
||||
return aliveTemp2(x);
|
||||
}
|
||||
|
||||
class MyClass
|
||||
{
|
||||
float F;
|
||||
float makeF() {
|
||||
// expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(F); // #MyClass_makeF_fx_call
|
||||
// expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(F); // #MyClass_makeF_fy_call
|
||||
// expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(F); // #MyClass_makeF_fz_call
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Exported function without body, not used
|
||||
export void exportedFunctionUnused(float f);
|
||||
|
||||
// Exported function with body, without export, not used
|
||||
void exportedFunctionUnused(float f) {
|
||||
// expected-error@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #exportedFunctionUnused_fx_call
|
||||
|
||||
// API with shader-stage-specific availability in unused exported library function
|
||||
// - no errors expected because the actual shader stage this function
|
||||
// will be used in not known at this time
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
}
|
||||
|
||||
// Exported function with body - called from main() which is a compute shader entry point
|
||||
export void exportedFunctionUsed(float f) {
|
||||
// expected-error@#exportedFunctionUsed_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #exportedFunctionUsed_fx_call
|
||||
|
||||
// expected-error@#exportedFunctionUsed_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #exportedFunctionUsed_fy_call
|
||||
|
||||
// expected-error@#exportedFunctionUsed_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #exportedFunctionUsed_fz_call
|
||||
}
|
||||
|
||||
namespace A {
|
||||
namespace B {
|
||||
export {
|
||||
void exportedFunctionInNS(float x) {
|
||||
// expected-error@#exportedFunctionInNS_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(x); // #exportedFunctionInNS_fx_call
|
||||
|
||||
// API with shader-stage-specific availability in exported library function
|
||||
// - no errors expected because the actual shader stage this function
|
||||
// will be used in not known at this time
|
||||
float B = fy(x);
|
||||
float C = fz(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shader entry point without body
|
||||
[shader("compute")]
|
||||
[numthreads(4,1,1)]
|
||||
float main();
|
||||
|
||||
// Shader entry point with body
|
||||
[shader("compute")]
|
||||
[numthreads(4,1,1)]
|
||||
float main() {
|
||||
float f = 3;
|
||||
MyClass C = { 1.0f };
|
||||
float a = alive(f);
|
||||
float b = aliveTemp<float>(f); // #aliveTemp_inst
|
||||
float c = C.makeF();
|
||||
float d = test((float)1.0);
|
||||
float e = test((half)1.0);
|
||||
exportedFunctionUsed(1.0f);
|
||||
return a * b * c;
|
||||
}
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \
|
||||
// RUN: -fsyntax-only -verify %s
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.5)))
|
||||
float fx(float); // #fx
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.6)))
|
||||
half fx(half); // #fx_half
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
|
||||
float fy(float); // #fy
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh)))
|
||||
float fz(float); // #fz
|
||||
|
||||
float also_alive(float f) {
|
||||
// expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #also_alive_fx_call
|
||||
|
||||
// expected-error@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #also_alive_fy_call
|
||||
|
||||
// expected-error@#also_alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #also_alive_fz_call
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float alive(float f) {
|
||||
// expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #alive_fx_call
|
||||
|
||||
// expected-error@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #alive_fy_call
|
||||
|
||||
// expected-error@#alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #alive_fz_call
|
||||
|
||||
return also_alive(f);
|
||||
}
|
||||
|
||||
float also_dead(float f) {
|
||||
// unreachable code - no errors expected
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float dead(float f) {
|
||||
// unreachable code - no errors expected
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
return also_dead(f);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T aliveTemp(T f) {
|
||||
// expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #aliveTemp_fx_call
|
||||
// expected-error@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #aliveTemp_fy_call
|
||||
// expected-error@#aliveTemp_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #aliveTemp_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T> T aliveTemp2(T f) {
|
||||
// expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}}
|
||||
// expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}}
|
||||
// expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
return fx(f); // #aliveTemp2_fx_call
|
||||
}
|
||||
|
||||
half test(half x) {
|
||||
return aliveTemp2(x);
|
||||
}
|
||||
|
||||
float test(float x) {
|
||||
return aliveTemp2(x);
|
||||
}
|
||||
|
||||
class MyClass
|
||||
{
|
||||
float F;
|
||||
float makeF() {
|
||||
// expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(F); // #MyClass_makeF_fx_call
|
||||
// expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(F); // #MyClass_makeF_fy_call
|
||||
// expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(F); // #MyClass_makeF_fz_call
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Exported function without body, not used
|
||||
export void exportedFunctionUnused(float f);
|
||||
|
||||
// Exported function with body, without export, not used
|
||||
void exportedFunctionUnused(float f) {
|
||||
// expected-error@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #exportedFunctionUnused_fx_call
|
||||
|
||||
// API with shader-stage-specific availability in unused exported library function
|
||||
// - no errors expected because the actual shader stage this function
|
||||
// will be used in not known at this time
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
}
|
||||
|
||||
// Exported function with body - called from main() which is a compute shader entry point
|
||||
export void exportedFunctionUsed(float f) {
|
||||
// expected-error@#exportedFunctionUsed_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #exportedFunctionUsed_fx_call
|
||||
|
||||
// expected-error@#exportedFunctionUsed_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #exportedFunctionUsed_fy_call
|
||||
|
||||
// expected-error@#exportedFunctionUsed_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #exportedFunctionUsed_fz_call
|
||||
}
|
||||
|
||||
namespace A {
|
||||
namespace B {
|
||||
export {
|
||||
void exportedFunctionInNS(float x) {
|
||||
// expected-error@#exportedFunctionInNS_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(x); // #exportedFunctionInNS_fx_call
|
||||
|
||||
// API with shader-stage-specific availability in exported library function
|
||||
// - no errors expected because the actual shader stage this function
|
||||
// will be used in not known at this time
|
||||
float B = fy(x);
|
||||
float C = fz(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shader entry point without body
|
||||
[shader("compute")]
|
||||
[numthreads(4,1,1)]
|
||||
float main();
|
||||
|
||||
// Shader entry point with body
|
||||
[shader("compute")]
|
||||
[numthreads(4,1,1)]
|
||||
float main() {
|
||||
float f = 3;
|
||||
MyClass C = { 1.0f };
|
||||
float a = alive(f);
|
||||
float b = aliveTemp<float>(f); // #aliveTemp_inst
|
||||
float c = C.makeF();
|
||||
float d = test((float)1.0);
|
||||
float e = test((half)1.0);
|
||||
exportedFunctionUsed(1.0f);
|
||||
return a * b * c;
|
||||
}
|
||||
|
@ -1,119 +1,119 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute \
|
||||
// RUN: -fsyntax-only -Wno-error=hlsl-availability -verify %s
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.5)))
|
||||
float fx(float); // #fx
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.6)))
|
||||
half fx(half); // #fx_half
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
|
||||
float fy(float); // #fy
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh)))
|
||||
float fz(float); // #fz
|
||||
|
||||
float also_alive(float f) {
|
||||
// expected-warning@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #also_alive_fx_call
|
||||
// expected-warning@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #also_alive_fy_call
|
||||
// expected-warning@#also_alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #also_alive_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
float alive(float f) {
|
||||
// expected-warning@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #alive_fx_call
|
||||
// expected-warning@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #alive_fy_call
|
||||
// expected-warning@#alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #alive_fz_call
|
||||
|
||||
return also_alive(f);
|
||||
}
|
||||
|
||||
float also_dead(float f) {
|
||||
// unreachable code - no errors expected
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float dead(float f) {
|
||||
// unreachable code - no errors expected
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
|
||||
return also_dead(f);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T aliveTemp(T f) {
|
||||
// expected-warning@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #aliveTemp_fx_call
|
||||
// expected-warning@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #aliveTemp_fy_call
|
||||
// expected-warning@#aliveTemp_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #aliveTemp_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T> T aliveTemp2(T f) {
|
||||
// expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}}
|
||||
// expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}}
|
||||
// expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
return fx(f); // #aliveTemp2_fx_call
|
||||
}
|
||||
|
||||
half test(half x) {
|
||||
return aliveTemp2(x);
|
||||
}
|
||||
|
||||
float test(float x) {
|
||||
return aliveTemp2(x);
|
||||
}
|
||||
|
||||
class MyClass
|
||||
{
|
||||
float F;
|
||||
float makeF() {
|
||||
// expected-warning@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(F); // #MyClass_makeF_fx_call
|
||||
// expected-warning@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(F); // #MyClass_makeF_fy_call
|
||||
// expected-warning@#MyClass_makeF_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(F); // #MyClass_makeF_fz_call
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
[numthreads(4,1,1)]
|
||||
float main() {
|
||||
float f = 3;
|
||||
MyClass C = { 1.0f };
|
||||
float a = alive(f);
|
||||
float b = aliveTemp<float>(f); // #aliveTemp_inst
|
||||
float c = C.makeF();
|
||||
float d = test((float)1.0);
|
||||
float e = test((half)1.0);
|
||||
return a * b * c;
|
||||
}
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute \
|
||||
// RUN: -fsyntax-only -Wno-error=hlsl-availability -verify %s
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.5)))
|
||||
float fx(float); // #fx
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.6)))
|
||||
half fx(half); // #fx_half
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
|
||||
float fy(float); // #fy
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh)))
|
||||
float fz(float); // #fz
|
||||
|
||||
float also_alive(float f) {
|
||||
// expected-warning@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #also_alive_fx_call
|
||||
// expected-warning@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #also_alive_fy_call
|
||||
// expected-warning@#also_alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #also_alive_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
float alive(float f) {
|
||||
// expected-warning@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #alive_fx_call
|
||||
// expected-warning@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #alive_fy_call
|
||||
// expected-warning@#alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #alive_fz_call
|
||||
|
||||
return also_alive(f);
|
||||
}
|
||||
|
||||
float also_dead(float f) {
|
||||
// unreachable code - no errors expected
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float dead(float f) {
|
||||
// unreachable code - no errors expected
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
|
||||
return also_dead(f);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T aliveTemp(T f) {
|
||||
// expected-warning@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #aliveTemp_fx_call
|
||||
// expected-warning@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #aliveTemp_fy_call
|
||||
// expected-warning@#aliveTemp_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #aliveTemp_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T> T aliveTemp2(T f) {
|
||||
// expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}}
|
||||
// expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}}
|
||||
// expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
return fx(f); // #aliveTemp2_fx_call
|
||||
}
|
||||
|
||||
half test(half x) {
|
||||
return aliveTemp2(x);
|
||||
}
|
||||
|
||||
float test(float x) {
|
||||
return aliveTemp2(x);
|
||||
}
|
||||
|
||||
class MyClass
|
||||
{
|
||||
float F;
|
||||
float makeF() {
|
||||
// expected-warning@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(F); // #MyClass_makeF_fx_call
|
||||
// expected-warning@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(F); // #MyClass_makeF_fy_call
|
||||
// expected-warning@#MyClass_makeF_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(F); // #MyClass_makeF_fz_call
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
[numthreads(4,1,1)]
|
||||
float main() {
|
||||
float f = 3;
|
||||
MyClass C = { 1.0f };
|
||||
float a = alive(f);
|
||||
float b = aliveTemp<float>(f); // #aliveTemp_inst
|
||||
float c = C.makeF();
|
||||
float d = test((float)1.0);
|
||||
float e = test((half)1.0);
|
||||
return a * b * c;
|
||||
}
|
||||
|
@ -1,162 +1,162 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \
|
||||
// RUN: -fsyntax-only -Wno-error=hlsl-availability -verify %s
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.5)))
|
||||
float fx(float); // #fx
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.6)))
|
||||
half fx(half); // #fx_half
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
|
||||
float fy(float); // #fy
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh)))
|
||||
float fz(float); // #fz
|
||||
|
||||
float also_alive(float f) {
|
||||
// expected-warning@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #also_alive_fx_call
|
||||
|
||||
// expected-warning@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #also_alive_fy_call
|
||||
|
||||
// expected-warning@#also_alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #also_alive_fz_call
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float alive(float f) {
|
||||
// expected-warning@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #alive_fx_call
|
||||
|
||||
// expected-warning@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #alive_fy_call
|
||||
|
||||
// expected-warning@#alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #alive_fz_call
|
||||
|
||||
return also_alive(f);
|
||||
}
|
||||
|
||||
float also_dead(float f) {
|
||||
// unreachable code - no errors expected
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float dead(float f) {
|
||||
// unreachable code - no errors expected
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
return also_dead(f);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T aliveTemp(T f) {
|
||||
// expected-warning@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #aliveTemp_fx_call
|
||||
// expected-warning@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #aliveTemp_fy_call
|
||||
// expected-warning@#aliveTemp_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #aliveTemp_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T> T aliveTemp2(T f) {
|
||||
// expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}}
|
||||
// expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}}
|
||||
// expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
return fx(f); // #aliveTemp2_fx_call
|
||||
}
|
||||
|
||||
half test(half x) {
|
||||
return aliveTemp2(x);
|
||||
}
|
||||
|
||||
float test(float x) {
|
||||
return aliveTemp2(x);
|
||||
}
|
||||
|
||||
class MyClass
|
||||
{
|
||||
float F;
|
||||
float makeF() {
|
||||
// expected-warning@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(F); // #MyClass_makeF_fx_call
|
||||
// expected-warning@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(F); // #MyClass_makeF_fy_call
|
||||
// expected-warning@#MyClass_makeF_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(F); // #MyClass_makeF_fz_call
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Exported function without body, not used
|
||||
export void exportedFunctionUnused(float f);
|
||||
|
||||
// Exported function with body, without export, not used
|
||||
void exportedFunctionUnused(float f) {
|
||||
// expected-warning@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #exportedFunctionUnused_fx_call
|
||||
|
||||
// API with shader-stage-specific availability in unused exported library function
|
||||
// - no errors expected because the actual shader stage this function
|
||||
// will be used in not known at this time
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
}
|
||||
|
||||
// Exported function with body - called from main() which is a compute shader entry point
|
||||
export void exportedFunctionUsed(float f) {
|
||||
// expected-warning@#exportedFunctionUsed_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #exportedFunctionUsed_fx_call
|
||||
|
||||
// expected-warning@#exportedFunctionUsed_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #exportedFunctionUsed_fy_call
|
||||
|
||||
// expected-warning@#exportedFunctionUsed_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #exportedFunctionUsed_fz_call
|
||||
}
|
||||
|
||||
// Shader entry point without body
|
||||
[shader("compute")]
|
||||
[numthreads(4,1,1)]
|
||||
float main();
|
||||
|
||||
// Shader entry point with body
|
||||
[shader("compute")]
|
||||
[numthreads(4,1,1)]
|
||||
float main() {
|
||||
float f = 3;
|
||||
MyClass C = { 1.0f };
|
||||
float a = alive(f);
|
||||
float b = aliveTemp<float>(f); // #aliveTemp_inst
|
||||
float c = C.makeF();
|
||||
float d = test((float)1.0);
|
||||
float e = test((half)1.0);
|
||||
exportedFunctionUsed(1.0f);
|
||||
return a * b * c;
|
||||
}
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \
|
||||
// RUN: -fsyntax-only -Wno-error=hlsl-availability -verify %s
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.5)))
|
||||
float fx(float); // #fx
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.6)))
|
||||
half fx(half); // #fx_half
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
|
||||
float fy(float); // #fy
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh)))
|
||||
float fz(float); // #fz
|
||||
|
||||
float also_alive(float f) {
|
||||
// expected-warning@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #also_alive_fx_call
|
||||
|
||||
// expected-warning@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #also_alive_fy_call
|
||||
|
||||
// expected-warning@#also_alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #also_alive_fz_call
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float alive(float f) {
|
||||
// expected-warning@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #alive_fx_call
|
||||
|
||||
// expected-warning@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #alive_fy_call
|
||||
|
||||
// expected-warning@#alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #alive_fz_call
|
||||
|
||||
return also_alive(f);
|
||||
}
|
||||
|
||||
float also_dead(float f) {
|
||||
// unreachable code - no errors expected
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float dead(float f) {
|
||||
// unreachable code - no errors expected
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
return also_dead(f);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T aliveTemp(T f) {
|
||||
// expected-warning@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #aliveTemp_fx_call
|
||||
// expected-warning@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #aliveTemp_fy_call
|
||||
// expected-warning@#aliveTemp_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #aliveTemp_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T> T aliveTemp2(T f) {
|
||||
// expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}}
|
||||
// expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}}
|
||||
// expected-warning@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
return fx(f); // #aliveTemp2_fx_call
|
||||
}
|
||||
|
||||
half test(half x) {
|
||||
return aliveTemp2(x);
|
||||
}
|
||||
|
||||
float test(float x) {
|
||||
return aliveTemp2(x);
|
||||
}
|
||||
|
||||
class MyClass
|
||||
{
|
||||
float F;
|
||||
float makeF() {
|
||||
// expected-warning@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(F); // #MyClass_makeF_fx_call
|
||||
// expected-warning@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(F); // #MyClass_makeF_fy_call
|
||||
// expected-warning@#MyClass_makeF_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(F); // #MyClass_makeF_fz_call
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Exported function without body, not used
|
||||
export void exportedFunctionUnused(float f);
|
||||
|
||||
// Exported function with body, without export, not used
|
||||
void exportedFunctionUnused(float f) {
|
||||
// expected-warning@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #exportedFunctionUnused_fx_call
|
||||
|
||||
// API with shader-stage-specific availability in unused exported library function
|
||||
// - no errors expected because the actual shader stage this function
|
||||
// will be used in not known at this time
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
}
|
||||
|
||||
// Exported function with body - called from main() which is a compute shader entry point
|
||||
export void exportedFunctionUsed(float f) {
|
||||
// expected-warning@#exportedFunctionUsed_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #exportedFunctionUsed_fx_call
|
||||
|
||||
// expected-warning@#exportedFunctionUsed_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #exportedFunctionUsed_fy_call
|
||||
|
||||
// expected-warning@#exportedFunctionUsed_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #exportedFunctionUsed_fz_call
|
||||
}
|
||||
|
||||
// Shader entry point without body
|
||||
[shader("compute")]
|
||||
[numthreads(4,1,1)]
|
||||
float main();
|
||||
|
||||
// Shader entry point with body
|
||||
[shader("compute")]
|
||||
[numthreads(4,1,1)]
|
||||
float main() {
|
||||
float f = 3;
|
||||
MyClass C = { 1.0f };
|
||||
float a = alive(f);
|
||||
float b = aliveTemp<float>(f); // #aliveTemp_inst
|
||||
float c = C.makeF();
|
||||
float d = test((float)1.0);
|
||||
float e = test((half)1.0);
|
||||
exportedFunctionUsed(1.0f);
|
||||
return a * b * c;
|
||||
}
|
||||
|
@ -1,129 +1,129 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute \
|
||||
// RUN: -fhlsl-strict-availability -fsyntax-only -verify %s
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.5)))
|
||||
float fx(float); // #fx
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.6)))
|
||||
half fx(half); // #fx_half
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
|
||||
float fy(float); // #fy
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh)))
|
||||
float fz(float); // #fz
|
||||
|
||||
float also_alive(float f) {
|
||||
// expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #also_alive_fx_call
|
||||
// expected-error@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #also_alive_fy_call
|
||||
// expected-error@#also_alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #also_alive_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
float alive(float f) {
|
||||
// expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #alive_fx_call
|
||||
// expected-error@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #alive_fy_call
|
||||
// expected-error@#alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #alive_fz_call
|
||||
|
||||
return also_alive(f);
|
||||
}
|
||||
|
||||
float also_dead(float f) {
|
||||
// expected-error@#also_dead_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #also_dead_fx_call
|
||||
// expected-error@#also_dead_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #also_dead_fy_call
|
||||
// expected-error@#also_dead_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #also_dead_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
float dead(float f) {
|
||||
// expected-error@#dead_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #dead_fx_call
|
||||
// expected-error@#dead_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #dead_fy_call
|
||||
// expected-error@#dead_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #dead_fz_call
|
||||
|
||||
return also_dead(f);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T aliveTemp(T f) {
|
||||
// expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#aliveTemp_inst {{in instantiation of function template specialization 'aliveTemp<float>' requested here}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #aliveTemp_fx_call
|
||||
// expected-error@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #aliveTemp_fy_call
|
||||
// expected-error@#aliveTemp_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #aliveTemp_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T> T aliveTemp2(T f) {
|
||||
// expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}}
|
||||
// expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}}
|
||||
// expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
return fx(f); // #aliveTemp2_fx_call
|
||||
}
|
||||
|
||||
half test(half x) {
|
||||
return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2<half>' requested here}}
|
||||
}
|
||||
|
||||
float test(float x) {
|
||||
return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2<float>' requested here}}
|
||||
}
|
||||
|
||||
class MyClass
|
||||
{
|
||||
float F;
|
||||
float makeF() {
|
||||
// expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(F); // #MyClass_makeF_fx_call
|
||||
// expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(F); // #MyClass_makeF_fy_call
|
||||
// expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(F); // #MyClass_makeF_fz_call
|
||||
}
|
||||
};
|
||||
|
||||
[numthreads(4,1,1)]
|
||||
float main() {
|
||||
float f = 3;
|
||||
MyClass C = { 1.0f };
|
||||
float a = alive(f);
|
||||
float b = aliveTemp<float>(f); // #aliveTemp_inst
|
||||
float c = C.makeF();
|
||||
float d = test((float)1.0);
|
||||
float e = test((half)1.0);
|
||||
return a * b * c;
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute \
|
||||
// RUN: -fhlsl-strict-availability -fsyntax-only -verify %s
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.5)))
|
||||
float fx(float); // #fx
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.6)))
|
||||
half fx(half); // #fx_half
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
|
||||
float fy(float); // #fy
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh)))
|
||||
float fz(float); // #fz
|
||||
|
||||
float also_alive(float f) {
|
||||
// expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #also_alive_fx_call
|
||||
// expected-error@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #also_alive_fy_call
|
||||
// expected-error@#also_alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #also_alive_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
float alive(float f) {
|
||||
// expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #alive_fx_call
|
||||
// expected-error@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #alive_fy_call
|
||||
// expected-error@#alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #alive_fz_call
|
||||
|
||||
return also_alive(f);
|
||||
}
|
||||
|
||||
float also_dead(float f) {
|
||||
// expected-error@#also_dead_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #also_dead_fx_call
|
||||
// expected-error@#also_dead_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #also_dead_fy_call
|
||||
// expected-error@#also_dead_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #also_dead_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
float dead(float f) {
|
||||
// expected-error@#dead_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #dead_fx_call
|
||||
// expected-error@#dead_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #dead_fy_call
|
||||
// expected-error@#dead_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #dead_fz_call
|
||||
|
||||
return also_dead(f);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T aliveTemp(T f) {
|
||||
// expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#aliveTemp_inst {{in instantiation of function template specialization 'aliveTemp<float>' requested here}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #aliveTemp_fx_call
|
||||
// expected-error@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #aliveTemp_fy_call
|
||||
// expected-error@#aliveTemp_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #aliveTemp_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T> T aliveTemp2(T f) {
|
||||
// expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}}
|
||||
// expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}}
|
||||
// expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
return fx(f); // #aliveTemp2_fx_call
|
||||
}
|
||||
|
||||
half test(half x) {
|
||||
return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2<half>' requested here}}
|
||||
}
|
||||
|
||||
float test(float x) {
|
||||
return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2<float>' requested here}}
|
||||
}
|
||||
|
||||
class MyClass
|
||||
{
|
||||
float F;
|
||||
float makeF() {
|
||||
// expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(F); // #MyClass_makeF_fx_call
|
||||
// expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(F); // #MyClass_makeF_fy_call
|
||||
// expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(F); // #MyClass_makeF_fz_call
|
||||
}
|
||||
};
|
||||
|
||||
[numthreads(4,1,1)]
|
||||
float main() {
|
||||
float f = 3;
|
||||
MyClass C = { 1.0f };
|
||||
float a = alive(f);
|
||||
float b = aliveTemp<float>(f); // #aliveTemp_inst
|
||||
float c = C.makeF();
|
||||
float d = test((float)1.0);
|
||||
float e = test((half)1.0);
|
||||
return a * b * c;
|
||||
}
|
@ -1,192 +1,192 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \
|
||||
// RUN: -fhlsl-strict-availability -fsyntax-only -verify %s
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.5)))
|
||||
float fx(float); // #fx
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.6)))
|
||||
half fx(half); // #fx_half
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
|
||||
float fy(float); // #fy
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh)))
|
||||
float fz(float); // #fz
|
||||
|
||||
// FIXME: all diagnostics marked as FUTURE will come alive when HLSL default
|
||||
// diagnostic mode is implemented in a future PR which will verify calls in
|
||||
// all functions that are reachable from the shader library entry points
|
||||
|
||||
float also_alive(float f) {
|
||||
// expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #also_alive_fx_call
|
||||
|
||||
// expected-error@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #also_alive_fy_call
|
||||
|
||||
// expected-error@#also_alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #also_alive_fz_call
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float alive(float f) {
|
||||
// expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #alive_fx_call
|
||||
|
||||
// expected-error@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #alive_fy_call
|
||||
|
||||
// expected-error@#alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #alive_fz_call
|
||||
|
||||
return also_alive(f);
|
||||
}
|
||||
|
||||
float also_dead(float f) {
|
||||
// expected-error@#also_dead_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #also_dead_fx_call
|
||||
|
||||
// Call to environment-specific function from an unreachable function
|
||||
// in a shader library - no diagnostic expected.
|
||||
float B = fy(f); // #also_dead_fy_call
|
||||
|
||||
// Call to environment-specific function from an unreachable function
|
||||
// in a shader library - no diagnostic expected.
|
||||
float C = fz(f); // #also_dead_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
float dead(float f) {
|
||||
// expected-error@#dead_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #dead_fx_call
|
||||
|
||||
// Call to environment-specific function from an unreachable function
|
||||
// in a shader library - no diagnostic expected.
|
||||
float B = fy(f); // #dead_fy_call
|
||||
|
||||
// Call to environment-specific function from an unreachable function
|
||||
// in a shader library - no diagnostic expected.
|
||||
float C = fz(f); // #dead_fz_call
|
||||
|
||||
return also_dead(f);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T aliveTemp(T f) {
|
||||
// expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#aliveTemp_inst {{in instantiation of function template specialization 'aliveTemp<float>' requested here}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #aliveTemp_fx_call
|
||||
// expected-error@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #aliveTemp_fy_call
|
||||
// expected-error@#aliveTemp_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #aliveTemp_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T> T aliveTemp2(T f) {
|
||||
// expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}}
|
||||
// expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}}
|
||||
// expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
return fx(f); // #aliveTemp2_fx_call
|
||||
}
|
||||
|
||||
half test(half x) {
|
||||
return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2<half>' requested here}}
|
||||
}
|
||||
|
||||
float test(float x) {
|
||||
return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2<float>' requested here}}
|
||||
}
|
||||
|
||||
class MyClass
|
||||
{
|
||||
float F;
|
||||
float makeF() {
|
||||
// expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(F); // #MyClass_makeF_fx_call
|
||||
// expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(F); // #MyClass_makeF_fy_call
|
||||
// expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(F); // #MyClass_makeF_fz_call
|
||||
}
|
||||
};
|
||||
|
||||
// Exported function without body, not used
|
||||
export void exportedFunctionUnused(float f);
|
||||
|
||||
// Exported function with body, without export, not used
|
||||
void exportedFunctionUnused(float f) {
|
||||
// expected-error@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #exportedFunctionUnused_fx_call
|
||||
|
||||
// API with shader-stage-specific availability in unused exported library function
|
||||
// - no errors expected because the actual shader stage this function
|
||||
// will be used in not known at this time
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
}
|
||||
|
||||
// Exported function with body - called from main() which is a compute shader entry point
|
||||
export void exportedFunctionUsed(float f) {
|
||||
// expected-error@#exportedFunctionUsed_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #exportedFunctionUsed_fx_call
|
||||
|
||||
// expected-error@#exportedFunctionUsed_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #exportedFunctionUsed_fy_call
|
||||
|
||||
// expected-error@#exportedFunctionUsed_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #exportedFunctionUsed_fz_call
|
||||
}
|
||||
|
||||
namespace A {
|
||||
namespace B {
|
||||
export {
|
||||
void exportedFunctionInNS(float x) {
|
||||
// expected-error@#exportedFunctionInNS_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(x); // #exportedFunctionInNS_fx_call
|
||||
|
||||
// API with shader-stage-specific availability in exported library function
|
||||
// - no errors expected because the actual shader stage this function
|
||||
// will be used in not known at this time
|
||||
float B = fy(x);
|
||||
float C = fz(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[shader("compute")]
|
||||
[numthreads(4,1,1)]
|
||||
float main() {
|
||||
float f = 3;
|
||||
MyClass C = { 1.0f };
|
||||
float a = alive(f);float b = aliveTemp<float>(f); // #aliveTemp_inst
|
||||
float c = C.makeF();
|
||||
float d = test((float)1.0);
|
||||
float e = test((half)1.0);
|
||||
exportedFunctionUsed(1.0f);
|
||||
return a * b * c;
|
||||
}
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \
|
||||
// RUN: -fhlsl-strict-availability -fsyntax-only -verify %s
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.5)))
|
||||
float fx(float); // #fx
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.6)))
|
||||
half fx(half); // #fx_half
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
|
||||
float fy(float); // #fy
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = mesh)))
|
||||
float fz(float); // #fz
|
||||
|
||||
// FIXME: all diagnostics marked as FUTURE will come alive when HLSL default
|
||||
// diagnostic mode is implemented in a future PR which will verify calls in
|
||||
// all functions that are reachable from the shader library entry points
|
||||
|
||||
float also_alive(float f) {
|
||||
// expected-error@#also_alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #also_alive_fx_call
|
||||
|
||||
// expected-error@#also_alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #also_alive_fy_call
|
||||
|
||||
// expected-error@#also_alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #also_alive_fz_call
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float alive(float f) {
|
||||
// expected-error@#alive_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #alive_fx_call
|
||||
|
||||
// expected-error@#alive_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #alive_fy_call
|
||||
|
||||
// expected-error@#alive_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #alive_fz_call
|
||||
|
||||
return also_alive(f);
|
||||
}
|
||||
|
||||
float also_dead(float f) {
|
||||
// expected-error@#also_dead_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #also_dead_fx_call
|
||||
|
||||
// Call to environment-specific function from an unreachable function
|
||||
// in a shader library - no diagnostic expected.
|
||||
float B = fy(f); // #also_dead_fy_call
|
||||
|
||||
// Call to environment-specific function from an unreachable function
|
||||
// in a shader library - no diagnostic expected.
|
||||
float C = fz(f); // #also_dead_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
float dead(float f) {
|
||||
// expected-error@#dead_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #dead_fx_call
|
||||
|
||||
// Call to environment-specific function from an unreachable function
|
||||
// in a shader library - no diagnostic expected.
|
||||
float B = fy(f); // #dead_fy_call
|
||||
|
||||
// Call to environment-specific function from an unreachable function
|
||||
// in a shader library - no diagnostic expected.
|
||||
float C = fz(f); // #dead_fz_call
|
||||
|
||||
return also_dead(f);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T aliveTemp(T f) {
|
||||
// expected-error@#aliveTemp_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#aliveTemp_inst {{in instantiation of function template specialization 'aliveTemp<float>' requested here}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #aliveTemp_fx_call
|
||||
// expected-error@#aliveTemp_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #aliveTemp_fy_call
|
||||
// expected-error@#aliveTemp_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #aliveTemp_fz_call
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T> T aliveTemp2(T f) {
|
||||
// expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.6 or newer}}
|
||||
// expected-note@#fx_half {{'fx' has been marked as being introduced in Shader Model 6.6 here, but the deployment target is Shader Model 6.0}}
|
||||
// expected-error@#aliveTemp2_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
return fx(f); // #aliveTemp2_fx_call
|
||||
}
|
||||
|
||||
half test(half x) {
|
||||
return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2<half>' requested here}}
|
||||
}
|
||||
|
||||
float test(float x) {
|
||||
return aliveTemp2(x); // expected-note {{in instantiation of function template specialization 'aliveTemp2<float>' requested here}}
|
||||
}
|
||||
|
||||
class MyClass
|
||||
{
|
||||
float F;
|
||||
float makeF() {
|
||||
// expected-error@#MyClass_makeF_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(F); // #MyClass_makeF_fx_call
|
||||
// expected-error@#MyClass_makeF_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(F); // #MyClass_makeF_fy_call
|
||||
// expected-error@#MyClass_makeF_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(F); // #MyClass_makeF_fz_call
|
||||
}
|
||||
};
|
||||
|
||||
// Exported function without body, not used
|
||||
export void exportedFunctionUnused(float f);
|
||||
|
||||
// Exported function with body, without export, not used
|
||||
void exportedFunctionUnused(float f) {
|
||||
// expected-error@#exportedFunctionUnused_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #exportedFunctionUnused_fx_call
|
||||
|
||||
// API with shader-stage-specific availability in unused exported library function
|
||||
// - no errors expected because the actual shader stage this function
|
||||
// will be used in not known at this time
|
||||
float B = fy(f);
|
||||
float C = fz(f);
|
||||
}
|
||||
|
||||
// Exported function with body - called from main() which is a compute shader entry point
|
||||
export void exportedFunctionUsed(float f) {
|
||||
// expected-error@#exportedFunctionUsed_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #exportedFunctionUsed_fx_call
|
||||
|
||||
// expected-error@#exportedFunctionUsed_fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #exportedFunctionUsed_fy_call
|
||||
|
||||
// expected-error@#exportedFunctionUsed_fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 6.5 in mesh environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float C = fz(f); // #exportedFunctionUsed_fz_call
|
||||
}
|
||||
|
||||
namespace A {
|
||||
namespace B {
|
||||
export {
|
||||
void exportedFunctionInNS(float x) {
|
||||
// expected-error@#exportedFunctionInNS_fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{'fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(x); // #exportedFunctionInNS_fx_call
|
||||
|
||||
// API with shader-stage-specific availability in exported library function
|
||||
// - no errors expected because the actual shader stage this function
|
||||
// will be used in not known at this time
|
||||
float B = fy(x);
|
||||
float C = fz(x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[shader("compute")]
|
||||
[numthreads(4,1,1)]
|
||||
float main() {
|
||||
float f = 3;
|
||||
MyClass C = { 1.0f };
|
||||
float a = alive(f);float b = aliveTemp<float>(f); // #aliveTemp_inst
|
||||
float c = C.makeF();
|
||||
float d = test((float)1.0);
|
||||
float e = test((half)1.0);
|
||||
exportedFunctionUsed(1.0f);
|
||||
return a * b * c;
|
||||
}
|
||||
|
@ -1,57 +1,57 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \
|
||||
// RUN: -fsyntax-only -verify %s
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.5)))
|
||||
float fx(float); // #fx
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
|
||||
float fy(float); // #fy
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = compute)))
|
||||
float fz(float); // #fz
|
||||
|
||||
|
||||
void F(float f) {
|
||||
// Make sure we only get this error once, even though this function is scanned twice - once
|
||||
// in compute shader context and once in pixel shader context.
|
||||
// expected-error@#fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #fx_call
|
||||
|
||||
// expected-error@#fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #fy_call
|
||||
|
||||
// expected-error@#fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 5.0 in compute environment here, but the deployment target is Shader Model 6.0 pixel environment}}
|
||||
float X = fz(f); // #fz_call
|
||||
}
|
||||
|
||||
void deadCode(float f) {
|
||||
// no diagnostics expected under default diagnostic mode
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float X = fz(f);
|
||||
}
|
||||
|
||||
// Pixel shader
|
||||
[shader("pixel")]
|
||||
void mainPixel() {
|
||||
F(1.0);
|
||||
}
|
||||
|
||||
// First Compute shader
|
||||
[shader("compute")]
|
||||
[numthreads(4,1,1)]
|
||||
void mainCompute1() {
|
||||
F(2.0);
|
||||
}
|
||||
|
||||
// Second compute shader to make sure we do not get duplicate messages if F is called
|
||||
// from multiple entry points.
|
||||
[shader("compute")]
|
||||
[numthreads(4,1,1)]
|
||||
void mainCompute2() {
|
||||
F(3.0);
|
||||
}
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library \
|
||||
// RUN: -fsyntax-only -verify %s
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 6.5)))
|
||||
float fx(float); // #fx
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = pixel)))
|
||||
__attribute__((availability(shadermodel, introduced = 6.5, environment = compute)))
|
||||
float fy(float); // #fy
|
||||
|
||||
__attribute__((availability(shadermodel, introduced = 5.0, environment = compute)))
|
||||
float fz(float); // #fz
|
||||
|
||||
|
||||
void F(float f) {
|
||||
// Make sure we only get this error once, even though this function is scanned twice - once
|
||||
// in compute shader context and once in pixel shader context.
|
||||
// expected-error@#fx_call {{'fx' is only available on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fx {{fx' has been marked as being introduced in Shader Model 6.5 here, but the deployment target is Shader Model 6.0}}
|
||||
float A = fx(f); // #fx_call
|
||||
|
||||
// expected-error@#fy_call {{'fy' is only available in compute environment on Shader Model 6.5 or newer}}
|
||||
// expected-note@#fy {{'fy' has been marked as being introduced in Shader Model 6.5 in compute environment here, but the deployment target is Shader Model 6.0 compute environment}}
|
||||
float B = fy(f); // #fy_call
|
||||
|
||||
// expected-error@#fz_call {{'fz' is unavailable}}
|
||||
// expected-note@#fz {{'fz' has been marked as being introduced in Shader Model 5.0 in compute environment here, but the deployment target is Shader Model 6.0 pixel environment}}
|
||||
float X = fz(f); // #fz_call
|
||||
}
|
||||
|
||||
void deadCode(float f) {
|
||||
// no diagnostics expected under default diagnostic mode
|
||||
float A = fx(f);
|
||||
float B = fy(f);
|
||||
float X = fz(f);
|
||||
}
|
||||
|
||||
// Pixel shader
|
||||
[shader("pixel")]
|
||||
void mainPixel() {
|
||||
F(1.0);
|
||||
}
|
||||
|
||||
// First Compute shader
|
||||
[shader("compute")]
|
||||
[numthreads(4,1,1)]
|
||||
void mainCompute1() {
|
||||
F(2.0);
|
||||
}
|
||||
|
||||
// Second compute shader to make sure we do not get duplicate messages if F is called
|
||||
// from multiple entry points.
|
||||
[shader("compute")]
|
||||
[numthreads(4,1,1)]
|
||||
void mainCompute2() {
|
||||
F(3.0);
|
||||
}
|
||||
|
@ -1,19 +1,19 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -fsyntax-only -verify %s
|
||||
|
||||
typedef vector<float, 3> float3;
|
||||
|
||||
StructuredBuffer<float3> Buffer;
|
||||
|
||||
// expected-error@+2 {{class template 'StructuredBuffer' requires template arguments}}
|
||||
// expected-note@*:* {{template declaration from hidden source: template <class element_type> class StructuredBuffer}}
|
||||
StructuredBuffer BufferErr1;
|
||||
|
||||
// expected-error@+2 {{too few template arguments for class template 'StructuredBuffer'}}
|
||||
// expected-note@*:* {{template declaration from hidden source: template <class element_type> class StructuredBuffer}}
|
||||
StructuredBuffer<> BufferErr2;
|
||||
|
||||
[numthreads(1,1,1)]
|
||||
void main() {
|
||||
(void)Buffer.h; // expected-error {{'h' is a private member of 'hlsl::StructuredBuffer<vector<float, 3>>'}}
|
||||
// expected-note@* {{implicitly declared private here}}
|
||||
}
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -fsyntax-only -verify %s
|
||||
|
||||
typedef vector<float, 3> float3;
|
||||
|
||||
StructuredBuffer<float3> Buffer;
|
||||
|
||||
// expected-error@+2 {{class template 'StructuredBuffer' requires template arguments}}
|
||||
// expected-note@*:* {{template declaration from hidden source: template <class element_type> class StructuredBuffer}}
|
||||
StructuredBuffer BufferErr1;
|
||||
|
||||
// expected-error@+2 {{too few template arguments for class template 'StructuredBuffer'}}
|
||||
// expected-note@*:* {{template declaration from hidden source: template <class element_type> class StructuredBuffer}}
|
||||
StructuredBuffer<> BufferErr2;
|
||||
|
||||
[numthreads(1,1,1)]
|
||||
void main() {
|
||||
(void)Buffer.h; // expected-error {{'h' is a private member of 'hlsl::StructuredBuffer<vector<float, 3>>'}}
|
||||
// expected-note@* {{implicitly declared private here}}
|
||||
}
|
||||
|
@ -1,43 +1,43 @@
|
||||
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify
|
||||
|
||||
void test_too_few_arg()
|
||||
{
|
||||
return __builtin_hlsl_cross();
|
||||
// expected-error@-1 {{too few arguments to function call, expected 2, have 0}}
|
||||
}
|
||||
|
||||
void test_too_many_arg(float3 p0)
|
||||
{
|
||||
return __builtin_hlsl_cross(p0, p0, p0);
|
||||
// expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
|
||||
}
|
||||
|
||||
bool builtin_bool_to_float_type_promotion(bool p1)
|
||||
{
|
||||
return __builtin_hlsl_cross(p1, p1);
|
||||
// expected-error@-1 {{passing 'bool' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
bool builtin_cross_int_to_float_promotion(int p1)
|
||||
{
|
||||
return __builtin_hlsl_cross(p1, p1);
|
||||
// expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
bool2 builtin_cross_int2_to_float2_promotion(int2 p1)
|
||||
{
|
||||
return __builtin_hlsl_cross(p1, p1);
|
||||
// expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
|
||||
}
|
||||
|
||||
float2 builtin_cross_float2(float2 p1, float2 p2)
|
||||
{
|
||||
return __builtin_hlsl_cross(p1, p2);
|
||||
// expected-error@-1 {{too many elements in vector operand (expected 3 elements, have 2)}}
|
||||
}
|
||||
|
||||
float3 builtin_cross_float3_int3(float3 p1, int3 p2)
|
||||
{
|
||||
return __builtin_hlsl_cross(p1, p2);
|
||||
// expected-error@-1 {{all arguments to '__builtin_hlsl_cross' must have the same type}}
|
||||
}
|
||||
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify
|
||||
|
||||
void test_too_few_arg()
|
||||
{
|
||||
return __builtin_hlsl_cross();
|
||||
// expected-error@-1 {{too few arguments to function call, expected 2, have 0}}
|
||||
}
|
||||
|
||||
void test_too_many_arg(float3 p0)
|
||||
{
|
||||
return __builtin_hlsl_cross(p0, p0, p0);
|
||||
// expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
|
||||
}
|
||||
|
||||
bool builtin_bool_to_float_type_promotion(bool p1)
|
||||
{
|
||||
return __builtin_hlsl_cross(p1, p1);
|
||||
// expected-error@-1 {{passing 'bool' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
bool builtin_cross_int_to_float_promotion(int p1)
|
||||
{
|
||||
return __builtin_hlsl_cross(p1, p1);
|
||||
// expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
bool2 builtin_cross_int2_to_float2_promotion(int2 p1)
|
||||
{
|
||||
return __builtin_hlsl_cross(p1, p1);
|
||||
// expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
|
||||
}
|
||||
|
||||
float2 builtin_cross_float2(float2 p1, float2 p2)
|
||||
{
|
||||
return __builtin_hlsl_cross(p1, p2);
|
||||
// expected-error@-1 {{too many elements in vector operand (expected 3 elements, have 2)}}
|
||||
}
|
||||
|
||||
float3 builtin_cross_float3_int3(float3 p1, int3 p2)
|
||||
{
|
||||
return __builtin_hlsl_cross(p1, p2);
|
||||
// expected-error@-1 {{all arguments to '__builtin_hlsl_cross' must have the same type}}
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_atan2
|
||||
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_fmod
|
||||
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_pow
|
||||
|
||||
double test_double_builtin(double p0, double p1) {
|
||||
return TEST_FUNC(p0, p1);
|
||||
// expected-error@-1 {{passing 'double' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
double2 test_vec_double_builtin(double2 p0, double2 p1) {
|
||||
return TEST_FUNC(p0, p1);
|
||||
// expected-error@-1 {{passing 'double2' (aka 'vector<double, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
|
||||
}
|
||||
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_atan2
|
||||
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_fmod
|
||||
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_pow
|
||||
|
||||
double test_double_builtin(double p0, double p1) {
|
||||
return TEST_FUNC(p0, p1);
|
||||
// expected-error@-1 {{passing 'double' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
double2 test_vec_double_builtin(double2 p0, double2 p1) {
|
||||
return TEST_FUNC(p0, p1);
|
||||
// expected-error@-1 {{passing 'double2' (aka 'vector<double, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
|
||||
}
|
||||
|
@ -1,32 +1,32 @@
|
||||
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify -verify-ignore-unexpected
|
||||
|
||||
|
||||
void test_too_few_arg()
|
||||
{
|
||||
return __builtin_hlsl_length();
|
||||
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
|
||||
}
|
||||
|
||||
void test_too_many_arg(float2 p0)
|
||||
{
|
||||
return __builtin_hlsl_length(p0, p0);
|
||||
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
|
||||
}
|
||||
|
||||
bool builtin_bool_to_float_type_promotion(bool p1)
|
||||
{
|
||||
return __builtin_hlsl_length(p1);
|
||||
// expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
bool builtin_length_int_to_float_promotion(int p1)
|
||||
{
|
||||
return __builtin_hlsl_length(p1);
|
||||
// expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
bool2 builtin_length_int2_to_float2_promotion(int2 p1)
|
||||
{
|
||||
return __builtin_hlsl_length(p1);
|
||||
// expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
|
||||
}
|
||||
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify -verify-ignore-unexpected
|
||||
|
||||
|
||||
void test_too_few_arg()
|
||||
{
|
||||
return __builtin_hlsl_length();
|
||||
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
|
||||
}
|
||||
|
||||
void test_too_many_arg(float2 p0)
|
||||
{
|
||||
return __builtin_hlsl_length(p0, p0);
|
||||
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
|
||||
}
|
||||
|
||||
bool builtin_bool_to_float_type_promotion(bool p1)
|
||||
{
|
||||
return __builtin_hlsl_length(p1);
|
||||
// expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
bool builtin_length_int_to_float_promotion(int p1)
|
||||
{
|
||||
return __builtin_hlsl_length(p1);
|
||||
// expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
bool2 builtin_length_int2_to_float2_promotion(int2 p1)
|
||||
{
|
||||
return __builtin_hlsl_length(p1);
|
||||
// expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
|
||||
}
|
||||
|
@ -1,31 +1,31 @@
|
||||
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify -verify-ignore-unexpected
|
||||
|
||||
void test_too_few_arg()
|
||||
{
|
||||
return __builtin_hlsl_normalize();
|
||||
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
|
||||
}
|
||||
|
||||
void test_too_many_arg(float2 p0)
|
||||
{
|
||||
return __builtin_hlsl_normalize(p0, p0);
|
||||
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
|
||||
}
|
||||
|
||||
bool builtin_bool_to_float_type_promotion(bool p1)
|
||||
{
|
||||
return __builtin_hlsl_normalize(p1);
|
||||
// expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
bool builtin_normalize_int_to_float_promotion(int p1)
|
||||
{
|
||||
return __builtin_hlsl_normalize(p1);
|
||||
// expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
bool2 builtin_normalize_int2_to_float2_promotion(int2 p1)
|
||||
{
|
||||
return __builtin_hlsl_normalize(p1);
|
||||
// expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
|
||||
}
|
||||
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify -verify-ignore-unexpected
|
||||
|
||||
void test_too_few_arg()
|
||||
{
|
||||
return __builtin_hlsl_normalize();
|
||||
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
|
||||
}
|
||||
|
||||
void test_too_many_arg(float2 p0)
|
||||
{
|
||||
return __builtin_hlsl_normalize(p0, p0);
|
||||
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
|
||||
}
|
||||
|
||||
bool builtin_bool_to_float_type_promotion(bool p1)
|
||||
{
|
||||
return __builtin_hlsl_normalize(p1);
|
||||
// expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
bool builtin_normalize_int_to_float_promotion(int p1)
|
||||
{
|
||||
return __builtin_hlsl_normalize(p1);
|
||||
// expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
bool2 builtin_normalize_int2_to_float2_promotion(int2 p1)
|
||||
{
|
||||
return __builtin_hlsl_normalize(p1);
|
||||
// expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
|
||||
}
|
||||
|
@ -1,31 +1,31 @@
|
||||
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify -verify-ignore-unexpected
|
||||
|
||||
void test_too_few_arg()
|
||||
{
|
||||
return __builtin_hlsl_step();
|
||||
// expected-error@-1 {{too few arguments to function call, expected 2, have 0}}
|
||||
}
|
||||
|
||||
void test_too_many_arg(float2 p0)
|
||||
{
|
||||
return __builtin_hlsl_step(p0, p0, p0);
|
||||
// expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
|
||||
}
|
||||
|
||||
bool builtin_bool_to_float_type_promotion(bool p1)
|
||||
{
|
||||
return __builtin_hlsl_step(p1, p1);
|
||||
// expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
bool builtin_step_int_to_float_promotion(int p1)
|
||||
{
|
||||
return __builtin_hlsl_step(p1, p1);
|
||||
// expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
bool2 builtin_step_int2_to_float2_promotion(int2 p1)
|
||||
{
|
||||
return __builtin_hlsl_step(p1, p1);
|
||||
// expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
|
||||
}
|
||||
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -disable-llvm-passes -verify -verify-ignore-unexpected
|
||||
|
||||
void test_too_few_arg()
|
||||
{
|
||||
return __builtin_hlsl_step();
|
||||
// expected-error@-1 {{too few arguments to function call, expected 2, have 0}}
|
||||
}
|
||||
|
||||
void test_too_many_arg(float2 p0)
|
||||
{
|
||||
return __builtin_hlsl_step(p0, p0, p0);
|
||||
// expected-error@-1 {{too many arguments to function call, expected 2, have 3}}
|
||||
}
|
||||
|
||||
bool builtin_bool_to_float_type_promotion(bool p1)
|
||||
{
|
||||
return __builtin_hlsl_step(p1, p1);
|
||||
// expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
bool builtin_step_int_to_float_promotion(int p1)
|
||||
{
|
||||
return __builtin_hlsl_step(p1, p1);
|
||||
// expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}}
|
||||
}
|
||||
|
||||
bool2 builtin_step_int2_to_float2_promotion(int2 p1)
|
||||
{
|
||||
return __builtin_hlsl_step(p1, p1);
|
||||
// expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
|
||||
}
|
||||
|
@ -1,81 +1,81 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -verify %s
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
_Static_assert(__builtin_hlsl_is_intangible(__hlsl_resource_t), "");
|
||||
// no need to check array of __hlsl_resource_t, arrays of sizeless types are not supported
|
||||
|
||||
_Static_assert(!__builtin_hlsl_is_intangible(int), "");
|
||||
_Static_assert(!__builtin_hlsl_is_intangible(float3), "");
|
||||
_Static_assert(!__builtin_hlsl_is_intangible(half[4]), "");
|
||||
|
||||
typedef __hlsl_resource_t Res;
|
||||
_Static_assert(__builtin_hlsl_is_intangible(const Res), "");
|
||||
// no need to check array of Res, arrays of sizeless types are not supported
|
||||
|
||||
struct ABuffer {
|
||||
const int i[10];
|
||||
__hlsl_resource_t h;
|
||||
};
|
||||
_Static_assert(__builtin_hlsl_is_intangible(ABuffer), "");
|
||||
_Static_assert(__builtin_hlsl_is_intangible(ABuffer[10]), "");
|
||||
|
||||
struct MyStruct {
|
||||
half2 h2;
|
||||
int3 i3;
|
||||
};
|
||||
_Static_assert(!__builtin_hlsl_is_intangible(MyStruct), "");
|
||||
_Static_assert(!__builtin_hlsl_is_intangible(MyStruct[10]), "");
|
||||
|
||||
class MyClass {
|
||||
int3 ivec;
|
||||
float farray[12];
|
||||
MyStruct ms;
|
||||
ABuffer buf;
|
||||
};
|
||||
_Static_assert(__builtin_hlsl_is_intangible(MyClass), "");
|
||||
_Static_assert(__builtin_hlsl_is_intangible(MyClass[2]), "");
|
||||
|
||||
union U {
|
||||
double d[4];
|
||||
Res buf;
|
||||
};
|
||||
_Static_assert(__builtin_hlsl_is_intangible(U), "");
|
||||
_Static_assert(__builtin_hlsl_is_intangible(U[100]), "");
|
||||
|
||||
class MyClass2 {
|
||||
int3 ivec;
|
||||
float farray[12];
|
||||
U u;
|
||||
};
|
||||
_Static_assert(__builtin_hlsl_is_intangible(MyClass2), "");
|
||||
_Static_assert(__builtin_hlsl_is_intangible(MyClass2[5]), "");
|
||||
|
||||
class Simple {
|
||||
int a;
|
||||
};
|
||||
|
||||
template<typename T> struct TemplatedBuffer {
|
||||
T a;
|
||||
__hlsl_resource_t h;
|
||||
};
|
||||
_Static_assert(__builtin_hlsl_is_intangible(TemplatedBuffer<int>), "");
|
||||
|
||||
struct MyStruct2 : TemplatedBuffer<float> {
|
||||
float x;
|
||||
};
|
||||
_Static_assert(__builtin_hlsl_is_intangible(MyStruct2), "");
|
||||
|
||||
struct MyStruct3 {
|
||||
const TemplatedBuffer<float> TB[10];
|
||||
};
|
||||
_Static_assert(__builtin_hlsl_is_intangible(MyStruct3), "");
|
||||
|
||||
template<typename T> struct SimpleTemplate {
|
||||
T a;
|
||||
};
|
||||
_Static_assert(__builtin_hlsl_is_intangible(SimpleTemplate<__hlsl_resource_t>), "");
|
||||
_Static_assert(!__builtin_hlsl_is_intangible(SimpleTemplate<float>), "");
|
||||
|
||||
_Static_assert(__builtin_hlsl_is_intangible(RWBuffer<float>), "");
|
||||
_Static_assert(__builtin_hlsl_is_intangible(StructuredBuffer<Simple>), "");
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -verify %s
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -fnative-half-type -verify %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
_Static_assert(__builtin_hlsl_is_intangible(__hlsl_resource_t), "");
|
||||
// no need to check array of __hlsl_resource_t, arrays of sizeless types are not supported
|
||||
|
||||
_Static_assert(!__builtin_hlsl_is_intangible(int), "");
|
||||
_Static_assert(!__builtin_hlsl_is_intangible(float3), "");
|
||||
_Static_assert(!__builtin_hlsl_is_intangible(half[4]), "");
|
||||
|
||||
typedef __hlsl_resource_t Res;
|
||||
_Static_assert(__builtin_hlsl_is_intangible(const Res), "");
|
||||
// no need to check array of Res, arrays of sizeless types are not supported
|
||||
|
||||
struct ABuffer {
|
||||
const int i[10];
|
||||
__hlsl_resource_t h;
|
||||
};
|
||||
_Static_assert(__builtin_hlsl_is_intangible(ABuffer), "");
|
||||
_Static_assert(__builtin_hlsl_is_intangible(ABuffer[10]), "");
|
||||
|
||||
struct MyStruct {
|
||||
half2 h2;
|
||||
int3 i3;
|
||||
};
|
||||
_Static_assert(!__builtin_hlsl_is_intangible(MyStruct), "");
|
||||
_Static_assert(!__builtin_hlsl_is_intangible(MyStruct[10]), "");
|
||||
|
||||
class MyClass {
|
||||
int3 ivec;
|
||||
float farray[12];
|
||||
MyStruct ms;
|
||||
ABuffer buf;
|
||||
};
|
||||
_Static_assert(__builtin_hlsl_is_intangible(MyClass), "");
|
||||
_Static_assert(__builtin_hlsl_is_intangible(MyClass[2]), "");
|
||||
|
||||
union U {
|
||||
double d[4];
|
||||
Res buf;
|
||||
};
|
||||
_Static_assert(__builtin_hlsl_is_intangible(U), "");
|
||||
_Static_assert(__builtin_hlsl_is_intangible(U[100]), "");
|
||||
|
||||
class MyClass2 {
|
||||
int3 ivec;
|
||||
float farray[12];
|
||||
U u;
|
||||
};
|
||||
_Static_assert(__builtin_hlsl_is_intangible(MyClass2), "");
|
||||
_Static_assert(__builtin_hlsl_is_intangible(MyClass2[5]), "");
|
||||
|
||||
class Simple {
|
||||
int a;
|
||||
};
|
||||
|
||||
template<typename T> struct TemplatedBuffer {
|
||||
T a;
|
||||
__hlsl_resource_t h;
|
||||
};
|
||||
_Static_assert(__builtin_hlsl_is_intangible(TemplatedBuffer<int>), "");
|
||||
|
||||
struct MyStruct2 : TemplatedBuffer<float> {
|
||||
float x;
|
||||
};
|
||||
_Static_assert(__builtin_hlsl_is_intangible(MyStruct2), "");
|
||||
|
||||
struct MyStruct3 {
|
||||
const TemplatedBuffer<float> TB[10];
|
||||
};
|
||||
_Static_assert(__builtin_hlsl_is_intangible(MyStruct3), "");
|
||||
|
||||
template<typename T> struct SimpleTemplate {
|
||||
T a;
|
||||
};
|
||||
_Static_assert(__builtin_hlsl_is_intangible(SimpleTemplate<__hlsl_resource_t>), "");
|
||||
_Static_assert(!__builtin_hlsl_is_intangible(SimpleTemplate<float>), "");
|
||||
|
||||
_Static_assert(__builtin_hlsl_is_intangible(RWBuffer<float>), "");
|
||||
_Static_assert(__builtin_hlsl_is_intangible(StructuredBuffer<Simple>), "");
|
||||
|
@ -1,12 +1,12 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -verify %s
|
||||
|
||||
struct Undefined; // expected-note {{forward declaration of 'Undefined'}}
|
||||
_Static_assert(!__builtin_hlsl_is_intangible(Undefined), ""); // expected-error{{incomplete type 'Undefined' used in type trait expression}}
|
||||
|
||||
void fn(int X) { // expected-note {{declared here}}
|
||||
// expected-error@#vla {{variable length arrays are not supported for the current target}}
|
||||
// expected-error@#vla {{variable length arrays are not supported in '__builtin_hlsl_is_intangible'}}
|
||||
// expected-warning@#vla {{variable length arrays in C++ are a Clang extension}}
|
||||
// expected-note@#vla {{function parameter 'X' with unknown value cannot be used in a constant expression}}
|
||||
_Static_assert(!__builtin_hlsl_is_intangible(int[X]), ""); // #vla
|
||||
}
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-library -finclude-default-header -verify %s
|
||||
|
||||
struct Undefined; // expected-note {{forward declaration of 'Undefined'}}
|
||||
_Static_assert(!__builtin_hlsl_is_intangible(Undefined), ""); // expected-error{{incomplete type 'Undefined' used in type trait expression}}
|
||||
|
||||
void fn(int X) { // expected-note {{declared here}}
|
||||
// expected-error@#vla {{variable length arrays are not supported for the current target}}
|
||||
// expected-error@#vla {{variable length arrays are not supported in '__builtin_hlsl_is_intangible'}}
|
||||
// expected-warning@#vla {{variable length arrays in C++ are a Clang extension}}
|
||||
// expected-note@#vla {{function parameter 'X' with unknown value cannot be used in a constant expression}}
|
||||
_Static_assert(!__builtin_hlsl_is_intangible(int[X]), ""); // #vla
|
||||
}
|
||||
|
@ -1,42 +1,42 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify
|
||||
|
||||
// expected-error@+1{{binding type 't' only applies to SRV resources}}
|
||||
float f1 : register(t0);
|
||||
|
||||
// expected-error@+1 {{binding type 'u' only applies to UAV resources}}
|
||||
float f2 : register(u0);
|
||||
|
||||
// expected-error@+1{{binding type 'b' only applies to constant buffers. The 'bool constant' binding type is no longer supported}}
|
||||
float f3 : register(b9);
|
||||
|
||||
// expected-error@+1 {{binding type 's' only applies to sampler state}}
|
||||
float f4 : register(s0);
|
||||
|
||||
// expected-error@+1{{binding type 'i' ignored. The 'integer constant' binding type is no longer supported}}
|
||||
float f5 : register(i9);
|
||||
|
||||
// expected-error@+1{{binding type 'x' is invalid}}
|
||||
float f6 : register(x9);
|
||||
|
||||
cbuffer g_cbuffer1 {
|
||||
// expected-error@+1{{binding type 'c' ignored in buffer declaration. Did you mean 'packoffset'?}}
|
||||
float f7 : register(c2);
|
||||
};
|
||||
|
||||
tbuffer g_tbuffer1 {
|
||||
// expected-error@+1{{binding type 'c' ignored in buffer declaration. Did you mean 'packoffset'?}}
|
||||
float f8 : register(c2);
|
||||
};
|
||||
|
||||
cbuffer g_cbuffer2 {
|
||||
// expected-error@+1{{binding type 'b' only applies to constant buffer resources}}
|
||||
float f9 : register(b2);
|
||||
};
|
||||
|
||||
tbuffer g_tbuffer2 {
|
||||
// expected-error@+1{{binding type 'i' ignored. The 'integer constant' binding type is no longer supported}}
|
||||
float f10 : register(i2);
|
||||
};
|
||||
|
||||
// expected-error@+1{{binding type 'c' only applies to numeric variables in the global scope}}
|
||||
RWBuffer<float> f11 : register(c3);
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify
|
||||
|
||||
// expected-error@+1{{binding type 't' only applies to SRV resources}}
|
||||
float f1 : register(t0);
|
||||
|
||||
// expected-error@+1 {{binding type 'u' only applies to UAV resources}}
|
||||
float f2 : register(u0);
|
||||
|
||||
// expected-error@+1{{binding type 'b' only applies to constant buffers. The 'bool constant' binding type is no longer supported}}
|
||||
float f3 : register(b9);
|
||||
|
||||
// expected-error@+1 {{binding type 's' only applies to sampler state}}
|
||||
float f4 : register(s0);
|
||||
|
||||
// expected-error@+1{{binding type 'i' ignored. The 'integer constant' binding type is no longer supported}}
|
||||
float f5 : register(i9);
|
||||
|
||||
// expected-error@+1{{binding type 'x' is invalid}}
|
||||
float f6 : register(x9);
|
||||
|
||||
cbuffer g_cbuffer1 {
|
||||
// expected-error@+1{{binding type 'c' ignored in buffer declaration. Did you mean 'packoffset'?}}
|
||||
float f7 : register(c2);
|
||||
};
|
||||
|
||||
tbuffer g_tbuffer1 {
|
||||
// expected-error@+1{{binding type 'c' ignored in buffer declaration. Did you mean 'packoffset'?}}
|
||||
float f8 : register(c2);
|
||||
};
|
||||
|
||||
cbuffer g_cbuffer2 {
|
||||
// expected-error@+1{{binding type 'b' only applies to constant buffer resources}}
|
||||
float f9 : register(b2);
|
||||
};
|
||||
|
||||
tbuffer g_tbuffer2 {
|
||||
// expected-error@+1{{binding type 'i' ignored. The 'integer constant' binding type is no longer supported}}
|
||||
float f10 : register(i2);
|
||||
};
|
||||
|
||||
// expected-error@+1{{binding type 'c' only applies to numeric variables in the global scope}}
|
||||
RWBuffer<float> f11 : register(c3);
|
||||
|
@ -1,9 +1,9 @@
|
||||
// RUN: not %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s | FileCheck %s
|
||||
|
||||
// XFAIL: *
|
||||
// This expectedly fails because RayQuery is an unsupported type.
|
||||
// When it becomes supported, we should expect an error due to
|
||||
// the variable type being classified as "other", and according
|
||||
// to the spec, err_hlsl_unsupported_register_type_and_variable_type
|
||||
// should be emitted.
|
||||
RayQuery<0> r1: register(t0);
|
||||
// RUN: not %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s | FileCheck %s
|
||||
|
||||
// XFAIL: *
|
||||
// This expectedly fails because RayQuery is an unsupported type.
|
||||
// When it becomes supported, we should expect an error due to
|
||||
// the variable type being classified as "other", and according
|
||||
// to the spec, err_hlsl_unsupported_register_type_and_variable_type
|
||||
// should be emitted.
|
||||
RayQuery<0> r1: register(t0);
|
||||
|
@ -1,49 +1,49 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify
|
||||
|
||||
// This test validates the diagnostics that are emitted when a variable with a "resource" type
|
||||
// is bound to a register using the register annotation
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct MyTemplatedSRV {
|
||||
__hlsl_resource_t [[hlsl::resource_class(SRV)]] x;
|
||||
};
|
||||
|
||||
struct MySRV {
|
||||
__hlsl_resource_t [[hlsl::resource_class(SRV)]] x;
|
||||
};
|
||||
|
||||
struct MySampler {
|
||||
__hlsl_resource_t [[hlsl::resource_class(Sampler)]] x;
|
||||
};
|
||||
|
||||
struct MyUAV {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] x;
|
||||
};
|
||||
|
||||
struct MyCBuffer {
|
||||
__hlsl_resource_t [[hlsl::resource_class(CBuffer)]] x;
|
||||
};
|
||||
|
||||
|
||||
// expected-error@+1 {{binding type 'i' ignored. The 'integer constant' binding type is no longer supported}}
|
||||
MySRV invalid : register(i2);
|
||||
|
||||
// expected-error@+1 {{binding type 't' only applies to SRV resources}}
|
||||
MyUAV a : register(t2, space1);
|
||||
|
||||
// expected-error@+1 {{binding type 'u' only applies to UAV resources}}
|
||||
MySampler b : register(u2, space1);
|
||||
|
||||
// expected-error@+1 {{binding type 'b' only applies to constant buffer resources}}
|
||||
MyTemplatedSRV<int> c : register(b2);
|
||||
|
||||
// expected-error@+1 {{binding type 's' only applies to sampler state}}
|
||||
MyUAV d : register(s2, space1);
|
||||
|
||||
// empty binding prefix cases:
|
||||
// expected-error@+1 {{expected identifier}}
|
||||
MyTemplatedSRV<int> e: register();
|
||||
|
||||
// expected-error@+1 {{expected identifier}}
|
||||
MyTemplatedSRV<int> f: register("");
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify
|
||||
|
||||
// This test validates the diagnostics that are emitted when a variable with a "resource" type
|
||||
// is bound to a register using the register annotation
|
||||
|
||||
|
||||
template<typename T>
|
||||
struct MyTemplatedSRV {
|
||||
__hlsl_resource_t [[hlsl::resource_class(SRV)]] x;
|
||||
};
|
||||
|
||||
struct MySRV {
|
||||
__hlsl_resource_t [[hlsl::resource_class(SRV)]] x;
|
||||
};
|
||||
|
||||
struct MySampler {
|
||||
__hlsl_resource_t [[hlsl::resource_class(Sampler)]] x;
|
||||
};
|
||||
|
||||
struct MyUAV {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] x;
|
||||
};
|
||||
|
||||
struct MyCBuffer {
|
||||
__hlsl_resource_t [[hlsl::resource_class(CBuffer)]] x;
|
||||
};
|
||||
|
||||
|
||||
// expected-error@+1 {{binding type 'i' ignored. The 'integer constant' binding type is no longer supported}}
|
||||
MySRV invalid : register(i2);
|
||||
|
||||
// expected-error@+1 {{binding type 't' only applies to SRV resources}}
|
||||
MyUAV a : register(t2, space1);
|
||||
|
||||
// expected-error@+1 {{binding type 'u' only applies to UAV resources}}
|
||||
MySampler b : register(u2, space1);
|
||||
|
||||
// expected-error@+1 {{binding type 'b' only applies to constant buffer resources}}
|
||||
MyTemplatedSRV<int> c : register(b2);
|
||||
|
||||
// expected-error@+1 {{binding type 's' only applies to sampler state}}
|
||||
MyUAV d : register(s2, space1);
|
||||
|
||||
// empty binding prefix cases:
|
||||
// expected-error@+1 {{expected identifier}}
|
||||
MyTemplatedSRV<int> e: register();
|
||||
|
||||
// expected-error@+1 {{expected identifier}}
|
||||
MyTemplatedSRV<int> f: register("");
|
||||
|
@ -1,27 +1,27 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only -Wno-legacy-constant-register-binding %s -verify
|
||||
|
||||
// expected-no-diagnostics
|
||||
float f2 : register(b9);
|
||||
|
||||
float f3 : register(i9);
|
||||
|
||||
cbuffer g_cbuffer1 {
|
||||
float f4 : register(c2);
|
||||
};
|
||||
|
||||
|
||||
struct Eg12{
|
||||
RWBuffer<int> a;
|
||||
};
|
||||
|
||||
Eg12 e12 : register(c9);
|
||||
|
||||
Eg12 bar : register(i1);
|
||||
|
||||
struct Eg7 {
|
||||
struct Bar {
|
||||
float f;
|
||||
};
|
||||
Bar b;
|
||||
};
|
||||
Eg7 e7 : register(t0);
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only -Wno-legacy-constant-register-binding %s -verify
|
||||
|
||||
// expected-no-diagnostics
|
||||
float f2 : register(b9);
|
||||
|
||||
float f3 : register(i9);
|
||||
|
||||
cbuffer g_cbuffer1 {
|
||||
float f4 : register(c2);
|
||||
};
|
||||
|
||||
|
||||
struct Eg12{
|
||||
RWBuffer<int> a;
|
||||
};
|
||||
|
||||
Eg12 e12 : register(c9);
|
||||
|
||||
Eg12 bar : register(i1);
|
||||
|
||||
struct Eg7 {
|
||||
struct Bar {
|
||||
float f;
|
||||
};
|
||||
Bar b;
|
||||
};
|
||||
Eg7 e7 : register(t0);
|
||||
|
@ -1,62 +1,62 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify
|
||||
|
||||
// valid
|
||||
cbuffer cbuf {
|
||||
RWBuffer<int> r : register(u0, space0);
|
||||
}
|
||||
|
||||
cbuffer cbuf2 {
|
||||
struct x {
|
||||
// this test validates that no diagnostic is emitted on the space parameter, because
|
||||
// this register annotation is not in the global scope.
|
||||
// expected-error@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}}
|
||||
RWBuffer<int> E : register(u2, space3);
|
||||
};
|
||||
}
|
||||
|
||||
struct MyStruct {
|
||||
RWBuffer<int> E;
|
||||
};
|
||||
|
||||
cbuffer cbuf3 {
|
||||
// valid
|
||||
MyStruct E : register(u2, space3);
|
||||
}
|
||||
|
||||
// valid
|
||||
MyStruct F : register(u3, space4);
|
||||
|
||||
cbuffer cbuf4 {
|
||||
// this test validates that no diagnostic is emitted on the space parameter, because
|
||||
// this register annotation is not in the global scope.
|
||||
// expected-error@+1 {{binding type 'u' only applies to UAV resources}}
|
||||
float a : register(u2, space3);
|
||||
}
|
||||
|
||||
// expected-error@+1 {{invalid space specifier 's2' used; expected 'space' followed by an integer, like space1}}
|
||||
cbuffer a : register(b0, s2) {
|
||||
|
||||
}
|
||||
|
||||
// expected-error@+1 {{invalid space specifier 'spaces' used; expected 'space' followed by an integer, like space1}}
|
||||
cbuffer b : register(b2, spaces) {
|
||||
|
||||
}
|
||||
|
||||
// expected-error@+1 {{wrong argument format for hlsl attribute, use space3 instead}}
|
||||
cbuffer c : register(b2, space 3) {}
|
||||
|
||||
// expected-error@+1 {{register space cannot be specified on global constants}}
|
||||
int d : register(c2, space3);
|
||||
|
||||
// expected-error@+1 {{register space cannot be specified on global constants}}
|
||||
int e : register(c2, space0);
|
||||
|
||||
// expected-error@+1 {{register space cannot be specified on global constants}}
|
||||
int f : register(c2, space00);
|
||||
|
||||
// valid
|
||||
RWBuffer<int> g : register(u2, space0);
|
||||
|
||||
// valid
|
||||
RWBuffer<int> h : register(u2, space0);
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify
|
||||
|
||||
// valid
|
||||
cbuffer cbuf {
|
||||
RWBuffer<int> r : register(u0, space0);
|
||||
}
|
||||
|
||||
cbuffer cbuf2 {
|
||||
struct x {
|
||||
// this test validates that no diagnostic is emitted on the space parameter, because
|
||||
// this register annotation is not in the global scope.
|
||||
// expected-error@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}}
|
||||
RWBuffer<int> E : register(u2, space3);
|
||||
};
|
||||
}
|
||||
|
||||
struct MyStruct {
|
||||
RWBuffer<int> E;
|
||||
};
|
||||
|
||||
cbuffer cbuf3 {
|
||||
// valid
|
||||
MyStruct E : register(u2, space3);
|
||||
}
|
||||
|
||||
// valid
|
||||
MyStruct F : register(u3, space4);
|
||||
|
||||
cbuffer cbuf4 {
|
||||
// this test validates that no diagnostic is emitted on the space parameter, because
|
||||
// this register annotation is not in the global scope.
|
||||
// expected-error@+1 {{binding type 'u' only applies to UAV resources}}
|
||||
float a : register(u2, space3);
|
||||
}
|
||||
|
||||
// expected-error@+1 {{invalid space specifier 's2' used; expected 'space' followed by an integer, like space1}}
|
||||
cbuffer a : register(b0, s2) {
|
||||
|
||||
}
|
||||
|
||||
// expected-error@+1 {{invalid space specifier 'spaces' used; expected 'space' followed by an integer, like space1}}
|
||||
cbuffer b : register(b2, spaces) {
|
||||
|
||||
}
|
||||
|
||||
// expected-error@+1 {{wrong argument format for hlsl attribute, use space3 instead}}
|
||||
cbuffer c : register(b2, space 3) {}
|
||||
|
||||
// expected-error@+1 {{register space cannot be specified on global constants}}
|
||||
int d : register(c2, space3);
|
||||
|
||||
// expected-error@+1 {{register space cannot be specified on global constants}}
|
||||
int e : register(c2, space0);
|
||||
|
||||
// expected-error@+1 {{register space cannot be specified on global constants}}
|
||||
int f : register(c2, space00);
|
||||
|
||||
// valid
|
||||
RWBuffer<int> g : register(u2, space0);
|
||||
|
||||
// valid
|
||||
RWBuffer<int> h : register(u2, space0);
|
||||
|
@ -1,135 +1,135 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify
|
||||
|
||||
template<typename T>
|
||||
struct MyTemplatedUAV {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] x;
|
||||
};
|
||||
|
||||
struct MySRV {
|
||||
__hlsl_resource_t [[hlsl::resource_class(SRV)]] x;
|
||||
};
|
||||
|
||||
struct MySampler {
|
||||
__hlsl_resource_t [[hlsl::resource_class(Sampler)]] x;
|
||||
};
|
||||
|
||||
struct MyUAV {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] x;
|
||||
};
|
||||
|
||||
struct MyCBuffer {
|
||||
__hlsl_resource_t [[hlsl::resource_class(CBuffer)]] x;
|
||||
};
|
||||
|
||||
// Valid: f is skipped, SRVBuf is bound to t0, UAVBuf is bound to u0
|
||||
struct Eg1 {
|
||||
float f;
|
||||
MySRV SRVBuf;
|
||||
MyUAV UAVBuf;
|
||||
};
|
||||
Eg1 e1 : register(t0) : register(u0);
|
||||
|
||||
// Valid: f is skipped, SRVBuf is bound to t0, UAVBuf is bound to u0.
|
||||
// UAVBuf2 gets automatically assigned to u1 even though there is no explicit binding for u1.
|
||||
struct Eg2 {
|
||||
float f;
|
||||
MySRV SRVBuf;
|
||||
MyUAV UAVBuf;
|
||||
MyUAV UAVBuf2;
|
||||
};
|
||||
Eg2 e2 : register(t0) : register(u0);
|
||||
|
||||
// Valid: Bar, the struct within Eg3, has a valid resource that can be bound to t0.
|
||||
struct Eg3 {
|
||||
struct Bar {
|
||||
MyUAV a;
|
||||
};
|
||||
Bar b;
|
||||
};
|
||||
Eg3 e3 : register(u0);
|
||||
|
||||
// Valid: the first sampler state object within 's' is bound to slot 5
|
||||
struct Eg4 {
|
||||
MySampler s[3];
|
||||
};
|
||||
|
||||
Eg4 e4 : register(s5);
|
||||
|
||||
|
||||
struct Eg5 {
|
||||
float f;
|
||||
};
|
||||
// expected-warning@+1{{binding type 't' only applies to types containing SRV resources}}
|
||||
Eg5 e5 : register(t0);
|
||||
|
||||
struct Eg6 {
|
||||
float f;
|
||||
};
|
||||
// expected-warning@+1{{binding type 'u' only applies to types containing UAV resources}}
|
||||
Eg6 e6 : register(u0);
|
||||
|
||||
struct Eg7 {
|
||||
float f;
|
||||
};
|
||||
// expected-warning@+1{{binding type 'b' only applies to types containing constant buffer resources}}
|
||||
Eg7 e7 : register(b0);
|
||||
|
||||
struct Eg8 {
|
||||
float f;
|
||||
};
|
||||
// expected-warning@+1{{binding type 's' only applies to types containing sampler state}}
|
||||
Eg8 e8 : register(s0);
|
||||
|
||||
struct Eg9 {
|
||||
MySRV s;
|
||||
};
|
||||
// expected-warning@+1{{binding type 'c' only applies to types containing numeric types}}
|
||||
Eg9 e9 : register(c0);
|
||||
|
||||
struct Eg10{
|
||||
// expected-error@+1{{'register' attribute only applies to cbuffer/tbuffer and external global variables}}
|
||||
MyTemplatedUAV<int> a : register(u9);
|
||||
};
|
||||
Eg10 e10;
|
||||
|
||||
|
||||
template<typename R>
|
||||
struct Eg11 {
|
||||
R b;
|
||||
};
|
||||
// expected-warning@+1{{binding type 'u' only applies to types containing UAV resources}}
|
||||
Eg11<MySRV> e11 : register(u0);
|
||||
// invalid because after template expansion, there are no valid resources inside Eg11 to bind as a UAV, only an SRV
|
||||
|
||||
|
||||
struct Eg12{
|
||||
MySRV s1;
|
||||
MySRV s2;
|
||||
};
|
||||
// expected-warning@+2{{binding type 'u' only applies to types containing UAV resources}}
|
||||
// expected-error@+1{{binding type 'u' cannot be applied more than once}}
|
||||
Eg12 e12 : register(u9) : register(u10);
|
||||
|
||||
struct Eg13{
|
||||
MySRV s1;
|
||||
MySRV s2;
|
||||
};
|
||||
// expected-warning@+3{{binding type 'u' only applies to types containing UAV resources}}
|
||||
// expected-error@+2{{binding type 'u' cannot be applied more than once}}
|
||||
// expected-error@+1{{binding type 'u' cannot be applied more than once}}
|
||||
Eg13 e13 : register(u9) : register(u10) : register(u11);
|
||||
|
||||
// expected-error@+1{{binding type 't' cannot be applied more than once}}
|
||||
Eg13 e13_2 : register(t11) : register(t12);
|
||||
|
||||
struct Eg14{
|
||||
MyTemplatedUAV<int> r1;
|
||||
};
|
||||
// expected-warning@+1{{binding type 't' only applies to types containing SRV resources}}
|
||||
Eg14 e14 : register(t9);
|
||||
|
||||
struct Eg15 {
|
||||
float f[4];
|
||||
};
|
||||
// expected no error
|
||||
Eg15 e15 : register(c0);
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify
|
||||
|
||||
template<typename T>
|
||||
struct MyTemplatedUAV {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] x;
|
||||
};
|
||||
|
||||
struct MySRV {
|
||||
__hlsl_resource_t [[hlsl::resource_class(SRV)]] x;
|
||||
};
|
||||
|
||||
struct MySampler {
|
||||
__hlsl_resource_t [[hlsl::resource_class(Sampler)]] x;
|
||||
};
|
||||
|
||||
struct MyUAV {
|
||||
__hlsl_resource_t [[hlsl::resource_class(UAV)]] x;
|
||||
};
|
||||
|
||||
struct MyCBuffer {
|
||||
__hlsl_resource_t [[hlsl::resource_class(CBuffer)]] x;
|
||||
};
|
||||
|
||||
// Valid: f is skipped, SRVBuf is bound to t0, UAVBuf is bound to u0
|
||||
struct Eg1 {
|
||||
float f;
|
||||
MySRV SRVBuf;
|
||||
MyUAV UAVBuf;
|
||||
};
|
||||
Eg1 e1 : register(t0) : register(u0);
|
||||
|
||||
// Valid: f is skipped, SRVBuf is bound to t0, UAVBuf is bound to u0.
|
||||
// UAVBuf2 gets automatically assigned to u1 even though there is no explicit binding for u1.
|
||||
struct Eg2 {
|
||||
float f;
|
||||
MySRV SRVBuf;
|
||||
MyUAV UAVBuf;
|
||||
MyUAV UAVBuf2;
|
||||
};
|
||||
Eg2 e2 : register(t0) : register(u0);
|
||||
|
||||
// Valid: Bar, the struct within Eg3, has a valid resource that can be bound to t0.
|
||||
struct Eg3 {
|
||||
struct Bar {
|
||||
MyUAV a;
|
||||
};
|
||||
Bar b;
|
||||
};
|
||||
Eg3 e3 : register(u0);
|
||||
|
||||
// Valid: the first sampler state object within 's' is bound to slot 5
|
||||
struct Eg4 {
|
||||
MySampler s[3];
|
||||
};
|
||||
|
||||
Eg4 e4 : register(s5);
|
||||
|
||||
|
||||
struct Eg5 {
|
||||
float f;
|
||||
};
|
||||
// expected-warning@+1{{binding type 't' only applies to types containing SRV resources}}
|
||||
Eg5 e5 : register(t0);
|
||||
|
||||
struct Eg6 {
|
||||
float f;
|
||||
};
|
||||
// expected-warning@+1{{binding type 'u' only applies to types containing UAV resources}}
|
||||
Eg6 e6 : register(u0);
|
||||
|
||||
struct Eg7 {
|
||||
float f;
|
||||
};
|
||||
// expected-warning@+1{{binding type 'b' only applies to types containing constant buffer resources}}
|
||||
Eg7 e7 : register(b0);
|
||||
|
||||
struct Eg8 {
|
||||
float f;
|
||||
};
|
||||
// expected-warning@+1{{binding type 's' only applies to types containing sampler state}}
|
||||
Eg8 e8 : register(s0);
|
||||
|
||||
struct Eg9 {
|
||||
MySRV s;
|
||||
};
|
||||
// expected-warning@+1{{binding type 'c' only applies to types containing numeric types}}
|
||||
Eg9 e9 : register(c0);
|
||||
|
||||
struct Eg10{
|
||||
// expected-error@+1{{'register' attribute only applies to cbuffer/tbuffer and external global variables}}
|
||||
MyTemplatedUAV<int> a : register(u9);
|
||||
};
|
||||
Eg10 e10;
|
||||
|
||||
|
||||
template<typename R>
|
||||
struct Eg11 {
|
||||
R b;
|
||||
};
|
||||
// expected-warning@+1{{binding type 'u' only applies to types containing UAV resources}}
|
||||
Eg11<MySRV> e11 : register(u0);
|
||||
// invalid because after template expansion, there are no valid resources inside Eg11 to bind as a UAV, only an SRV
|
||||
|
||||
|
||||
struct Eg12{
|
||||
MySRV s1;
|
||||
MySRV s2;
|
||||
};
|
||||
// expected-warning@+2{{binding type 'u' only applies to types containing UAV resources}}
|
||||
// expected-error@+1{{binding type 'u' cannot be applied more than once}}
|
||||
Eg12 e12 : register(u9) : register(u10);
|
||||
|
||||
struct Eg13{
|
||||
MySRV s1;
|
||||
MySRV s2;
|
||||
};
|
||||
// expected-warning@+3{{binding type 'u' only applies to types containing UAV resources}}
|
||||
// expected-error@+2{{binding type 'u' cannot be applied more than once}}
|
||||
// expected-error@+1{{binding type 'u' cannot be applied more than once}}
|
||||
Eg13 e13 : register(u9) : register(u10) : register(u11);
|
||||
|
||||
// expected-error@+1{{binding type 't' cannot be applied more than once}}
|
||||
Eg13 e13_2 : register(t11) : register(t12);
|
||||
|
||||
struct Eg14{
|
||||
MyTemplatedUAV<int> r1;
|
||||
};
|
||||
// expected-warning@+1{{binding type 't' only applies to types containing SRV resources}}
|
||||
Eg14 e14 : register(t9);
|
||||
|
||||
struct Eg15 {
|
||||
float f[4];
|
||||
};
|
||||
// expected no error
|
||||
Eg15 e15 : register(c0);
|
||||
|
@ -1 +1 @@
|
||||
perl -S scan-build %*
|
||||
perl -S scan-build %*
|
||||
|
@ -1 +1 @@
|
||||
perl -S c++-analyzer %*
|
||||
perl -S c++-analyzer %*
|
||||
|
@ -1 +1 @@
|
||||
perl -S ccc-analyzer %*
|
||||
perl -S ccc-analyzer %*
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,36 +1,36 @@
|
||||
! RUN: %flang -### --target=aarch64-windows-msvc -resource-dir=%S/Inputs/resource_dir %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC
|
||||
! RUN: %flang -### --target=aarch64-windows-msvc -resource-dir=%S/Inputs/resource_dir -fms-runtime-lib=static_dbg %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DEBUG
|
||||
! RUN: %flang -### --target=aarch64-windows-msvc -resource-dir=%S/Inputs/resource_dir -fms-runtime-lib=dll %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DLL
|
||||
! RUN: %flang -### --target=aarch64-windows-msvc -resource-dir=%S/Inputs/resource_dir -fms-runtime-lib=dll_dbg %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DLL-DEBUG
|
||||
|
||||
! MSVC: -fc1
|
||||
! MSVC-SAME: --dependent-lib=clang_rt.builtins.lib
|
||||
! MSVC-SAME: -D_MT
|
||||
! MSVC-SAME: --dependent-lib=libcmt
|
||||
! MSVC-SAME: --dependent-lib=FortranRuntime.static.lib
|
||||
! MSVC-SAME: --dependent-lib=FortranDecimal.static.lib
|
||||
|
||||
! MSVC-DEBUG: -fc1
|
||||
! MSVC-DEBUG-SAME: --dependent-lib=clang_rt.builtins.lib
|
||||
! MSVC-DEBUG-SAME: -D_MT
|
||||
! MSVC-DEBUG-SAME: -D_DEBUG
|
||||
! MSVC-DEBUG-SAME: --dependent-lib=libcmtd
|
||||
! MSVC-DEBUG-SAME: --dependent-lib=FortranRuntime.static_dbg.lib
|
||||
! MSVC-DEBUG-SAME: --dependent-lib=FortranDecimal.static_dbg.lib
|
||||
|
||||
! MSVC-DLL: -fc1
|
||||
! MSVC-DLL-SAME: --dependent-lib=clang_rt.builtins.lib
|
||||
! MSVC-DLL-SAME: -D_MT
|
||||
! MSVC-DLL-SAME: -D_DLL
|
||||
! MSVC-DLL-SAME: --dependent-lib=msvcrt
|
||||
! MSVC-DLL-SAME: --dependent-lib=FortranRuntime.dynamic.lib
|
||||
! MSVC-DLL-SAME: --dependent-lib=FortranDecimal.dynamic.lib
|
||||
|
||||
! MSVC-DLL-DEBUG: -fc1
|
||||
! MSVC-DLL-DEBUG-SAME: --dependent-lib=clang_rt.builtins.lib
|
||||
! MSVC-DLL-DEBUG-SAME: -D_MT
|
||||
! MSVC-DLL-DEBUG-SAME: -D_DEBUG
|
||||
! MSVC-DLL-DEBUG-SAME: -D_DLL
|
||||
! MSVC-DLL-DEBUG-SAME: --dependent-lib=msvcrtd
|
||||
! MSVC-DLL-DEBUG-SAME: --dependent-lib=FortranRuntime.dynamic_dbg.lib
|
||||
! MSVC-DLL-DEBUG-SAME: --dependent-lib=FortranDecimal.dynamic_dbg.lib
|
||||
! RUN: %flang -### --target=aarch64-windows-msvc -resource-dir=%S/Inputs/resource_dir %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC
|
||||
! RUN: %flang -### --target=aarch64-windows-msvc -resource-dir=%S/Inputs/resource_dir -fms-runtime-lib=static_dbg %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DEBUG
|
||||
! RUN: %flang -### --target=aarch64-windows-msvc -resource-dir=%S/Inputs/resource_dir -fms-runtime-lib=dll %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DLL
|
||||
! RUN: %flang -### --target=aarch64-windows-msvc -resource-dir=%S/Inputs/resource_dir -fms-runtime-lib=dll_dbg %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DLL-DEBUG
|
||||
|
||||
! MSVC: -fc1
|
||||
! MSVC-SAME: --dependent-lib=clang_rt.builtins.lib
|
||||
! MSVC-SAME: -D_MT
|
||||
! MSVC-SAME: --dependent-lib=libcmt
|
||||
! MSVC-SAME: --dependent-lib=FortranRuntime.static.lib
|
||||
! MSVC-SAME: --dependent-lib=FortranDecimal.static.lib
|
||||
|
||||
! MSVC-DEBUG: -fc1
|
||||
! MSVC-DEBUG-SAME: --dependent-lib=clang_rt.builtins.lib
|
||||
! MSVC-DEBUG-SAME: -D_MT
|
||||
! MSVC-DEBUG-SAME: -D_DEBUG
|
||||
! MSVC-DEBUG-SAME: --dependent-lib=libcmtd
|
||||
! MSVC-DEBUG-SAME: --dependent-lib=FortranRuntime.static_dbg.lib
|
||||
! MSVC-DEBUG-SAME: --dependent-lib=FortranDecimal.static_dbg.lib
|
||||
|
||||
! MSVC-DLL: -fc1
|
||||
! MSVC-DLL-SAME: --dependent-lib=clang_rt.builtins.lib
|
||||
! MSVC-DLL-SAME: -D_MT
|
||||
! MSVC-DLL-SAME: -D_DLL
|
||||
! MSVC-DLL-SAME: --dependent-lib=msvcrt
|
||||
! MSVC-DLL-SAME: --dependent-lib=FortranRuntime.dynamic.lib
|
||||
! MSVC-DLL-SAME: --dependent-lib=FortranDecimal.dynamic.lib
|
||||
|
||||
! MSVC-DLL-DEBUG: -fc1
|
||||
! MSVC-DLL-DEBUG-SAME: --dependent-lib=clang_rt.builtins.lib
|
||||
! MSVC-DLL-DEBUG-SAME: -D_MT
|
||||
! MSVC-DLL-DEBUG-SAME: -D_DEBUG
|
||||
! MSVC-DLL-DEBUG-SAME: -D_DLL
|
||||
! MSVC-DLL-DEBUG-SAME: --dependent-lib=msvcrtd
|
||||
! MSVC-DLL-DEBUG-SAME: --dependent-lib=FortranRuntime.dynamic_dbg.lib
|
||||
! MSVC-DLL-DEBUG-SAME: --dependent-lib=FortranDecimal.dynamic_dbg.lib
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include Makefile.rules
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include Makefile.rules
|
||||
|
@ -1,2 +1,2 @@
|
||||
MODULE windows x86 0F45B7919A9646F9BF8F2D6076EA421A11 fizzbuzz.pdb
|
||||
PUBLIC 1000 0 main
|
||||
MODULE windows x86 0F45B7919A9646F9BF8F2D6076EA421A11 fizzbuzz.pdb
|
||||
PUBLIC 1000 0 main
|
||||
|
@ -1,23 +1,23 @@
|
||||
CXX_SOURCES := main.cpp
|
||||
LD_EXTRAS := -L. -l_d -l_c -l_a -l_b
|
||||
|
||||
a.out: lib_b lib_a lib_c lib_d
|
||||
|
||||
include Makefile.rules
|
||||
|
||||
lib_a: lib_b
|
||||
"$(MAKE)" -f $(MAKEFILE_RULES) \
|
||||
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=a.cpp DYLIB_NAME=_a \
|
||||
LD_EXTRAS="-L. -l_b"
|
||||
|
||||
lib_b:
|
||||
"$(MAKE)" -f $(MAKEFILE_RULES) \
|
||||
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=_b
|
||||
|
||||
lib_c:
|
||||
"$(MAKE)" -f $(MAKEFILE_RULES) \
|
||||
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=c.cpp DYLIB_NAME=_c
|
||||
|
||||
lib_d:
|
||||
"$(MAKE)" -f $(MAKEFILE_RULES) \
|
||||
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=_d
|
||||
CXX_SOURCES := main.cpp
|
||||
LD_EXTRAS := -L. -l_d -l_c -l_a -l_b
|
||||
|
||||
a.out: lib_b lib_a lib_c lib_d
|
||||
|
||||
include Makefile.rules
|
||||
|
||||
lib_a: lib_b
|
||||
"$(MAKE)" -f $(MAKEFILE_RULES) \
|
||||
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=a.cpp DYLIB_NAME=_a \
|
||||
LD_EXTRAS="-L. -l_b"
|
||||
|
||||
lib_b:
|
||||
"$(MAKE)" -f $(MAKEFILE_RULES) \
|
||||
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=b.cpp DYLIB_NAME=_b
|
||||
|
||||
lib_c:
|
||||
"$(MAKE)" -f $(MAKEFILE_RULES) \
|
||||
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=c.cpp DYLIB_NAME=_c
|
||||
|
||||
lib_d:
|
||||
"$(MAKE)" -f $(MAKEFILE_RULES) \
|
||||
DYLIB_ONLY=YES DYLIB_CXX_SOURCES=d.cpp DYLIB_NAME=_d
|
||||
|
@ -1,3 +1,3 @@
|
||||
extern "C" int b_function();
|
||||
|
||||
extern "C" int a_function() { return b_function(); }
|
||||
extern "C" int b_function();
|
||||
|
||||
extern "C" int a_function() { return b_function(); }
|
||||
|
@ -1 +1 @@
|
||||
extern "C" int b_function() { return 500; }
|
||||
extern "C" int b_function() { return 500; }
|
||||
|
@ -1 +1 @@
|
||||
extern "C" int c_function() { return 600; }
|
||||
extern "C" int c_function() { return 600; }
|
||||
|
@ -1 +1 @@
|
||||
extern "C" int d_function() { return 700; }
|
||||
extern "C" int d_function() { return 700; }
|
||||
|
@ -1,16 +1,16 @@
|
||||
#include <stdio.h>
|
||||
|
||||
extern "C" int a_function();
|
||||
extern "C" int c_function();
|
||||
extern "C" int b_function();
|
||||
extern "C" int d_function();
|
||||
|
||||
int main() {
|
||||
a_function();
|
||||
b_function();
|
||||
c_function();
|
||||
d_function();
|
||||
|
||||
puts("running"); // breakpoint here
|
||||
return 0;
|
||||
}
|
||||
#include <stdio.h>
|
||||
|
||||
extern "C" int a_function();
|
||||
extern "C" int c_function();
|
||||
extern "C" int b_function();
|
||||
extern "C" int d_function();
|
||||
|
||||
int main() {
|
||||
a_function();
|
||||
b_function();
|
||||
c_function();
|
||||
d_function();
|
||||
|
||||
puts("running"); // breakpoint here
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
C_SOURCES := main.c
|
||||
|
||||
include Makefile.rules
|
||||
C_SOURCES := main.c
|
||||
|
||||
include Makefile.rules
|
||||
|
@ -1,88 +1,88 @@
|
||||
"""
|
||||
Test that line information is recalculated properly for a frame when it moves
|
||||
from the middle of the backtrace to a zero index.
|
||||
|
||||
This is a regression test for a StackFrame bug, where whether frame is zero or
|
||||
not depends on an internal field. When LLDB was updating its frame list value
|
||||
of the field wasn't copied into existing StackFrame instances, so those
|
||||
StackFrame instances, would use an incorrect line entry evaluation logic in
|
||||
situations if it was in the middle of the stack frame list (not zeroth), and
|
||||
then moved to the top position. The difference in logic is that for zeroth
|
||||
frames line entry is returned for program counter, while for other frame
|
||||
(except for those that "behave like zeroth") it is for the instruction
|
||||
preceding PC, as PC points to the next instruction after function call. When
|
||||
the bug is present, when execution stops at the second breakpoint
|
||||
SBFrame.GetLineEntry() returns line entry for the previous line, rather than
|
||||
the one with a breakpoint. Note that this is specific to
|
||||
SBFrame.GetLineEntry(), SBFrame.GetPCAddress().GetLineEntry() would return
|
||||
correct entry.
|
||||
|
||||
This bug doesn't reproduce through an LLDB interpretator, however it happens
|
||||
when using API directly, for example in LLDB-MI.
|
||||
"""
|
||||
|
||||
import lldb
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
|
||||
class ZerothFrame(TestBase):
|
||||
def test(self):
|
||||
"""
|
||||
Test that line information is recalculated properly for a frame when it moves
|
||||
from the middle of the backtrace to a zero index.
|
||||
"""
|
||||
self.build()
|
||||
self.setTearDownCleanup()
|
||||
|
||||
exe = self.getBuildArtifact("a.out")
|
||||
target = self.dbg.CreateTarget(exe)
|
||||
self.assertTrue(target, VALID_TARGET)
|
||||
|
||||
main_dot_c = lldb.SBFileSpec("main.c")
|
||||
bp1 = target.BreakpointCreateBySourceRegex(
|
||||
"// Set breakpoint 1 here", main_dot_c
|
||||
)
|
||||
bp2 = target.BreakpointCreateBySourceRegex(
|
||||
"// Set breakpoint 2 here", main_dot_c
|
||||
)
|
||||
|
||||
process = target.LaunchSimple(None, None, self.get_process_working_directory())
|
||||
self.assertTrue(process, VALID_PROCESS)
|
||||
|
||||
thread = self.thread()
|
||||
|
||||
if self.TraceOn():
|
||||
print("Backtrace at the first breakpoint:")
|
||||
for f in thread.frames:
|
||||
print(f)
|
||||
|
||||
# Check that we have stopped at correct breakpoint.
|
||||
self.assertEqual(
|
||||
thread.frame[0].GetLineEntry().GetLine(),
|
||||
bp1.GetLocationAtIndex(0).GetAddress().GetLineEntry().GetLine(),
|
||||
"LLDB reported incorrect line number.",
|
||||
)
|
||||
|
||||
# Important to use SBProcess::Continue() instead of
|
||||
# self.runCmd('continue'), because the problem doesn't reproduce with
|
||||
# 'continue' command.
|
||||
process.Continue()
|
||||
|
||||
if self.TraceOn():
|
||||
print("Backtrace at the second breakpoint:")
|
||||
for f in thread.frames:
|
||||
print(f)
|
||||
# Check that we have stopped at the breakpoint
|
||||
self.assertEqual(
|
||||
thread.frame[0].GetLineEntry().GetLine(),
|
||||
bp2.GetLocationAtIndex(0).GetAddress().GetLineEntry().GetLine(),
|
||||
"LLDB reported incorrect line number.",
|
||||
)
|
||||
# Double-check with GetPCAddress()
|
||||
self.assertEqual(
|
||||
thread.frame[0].GetLineEntry().GetLine(),
|
||||
thread.frame[0].GetPCAddress().GetLineEntry().GetLine(),
|
||||
"LLDB reported incorrect line number.",
|
||||
)
|
||||
"""
|
||||
Test that line information is recalculated properly for a frame when it moves
|
||||
from the middle of the backtrace to a zero index.
|
||||
|
||||
This is a regression test for a StackFrame bug, where whether frame is zero or
|
||||
not depends on an internal field. When LLDB was updating its frame list value
|
||||
of the field wasn't copied into existing StackFrame instances, so those
|
||||
StackFrame instances, would use an incorrect line entry evaluation logic in
|
||||
situations if it was in the middle of the stack frame list (not zeroth), and
|
||||
then moved to the top position. The difference in logic is that for zeroth
|
||||
frames line entry is returned for program counter, while for other frame
|
||||
(except for those that "behave like zeroth") it is for the instruction
|
||||
preceding PC, as PC points to the next instruction after function call. When
|
||||
the bug is present, when execution stops at the second breakpoint
|
||||
SBFrame.GetLineEntry() returns line entry for the previous line, rather than
|
||||
the one with a breakpoint. Note that this is specific to
|
||||
SBFrame.GetLineEntry(), SBFrame.GetPCAddress().GetLineEntry() would return
|
||||
correct entry.
|
||||
|
||||
This bug doesn't reproduce through an LLDB interpretator, however it happens
|
||||
when using API directly, for example in LLDB-MI.
|
||||
"""
|
||||
|
||||
import lldb
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
|
||||
class ZerothFrame(TestBase):
|
||||
def test(self):
|
||||
"""
|
||||
Test that line information is recalculated properly for a frame when it moves
|
||||
from the middle of the backtrace to a zero index.
|
||||
"""
|
||||
self.build()
|
||||
self.setTearDownCleanup()
|
||||
|
||||
exe = self.getBuildArtifact("a.out")
|
||||
target = self.dbg.CreateTarget(exe)
|
||||
self.assertTrue(target, VALID_TARGET)
|
||||
|
||||
main_dot_c = lldb.SBFileSpec("main.c")
|
||||
bp1 = target.BreakpointCreateBySourceRegex(
|
||||
"// Set breakpoint 1 here", main_dot_c
|
||||
)
|
||||
bp2 = target.BreakpointCreateBySourceRegex(
|
||||
"// Set breakpoint 2 here", main_dot_c
|
||||
)
|
||||
|
||||
process = target.LaunchSimple(None, None, self.get_process_working_directory())
|
||||
self.assertTrue(process, VALID_PROCESS)
|
||||
|
||||
thread = self.thread()
|
||||
|
||||
if self.TraceOn():
|
||||
print("Backtrace at the first breakpoint:")
|
||||
for f in thread.frames:
|
||||
print(f)
|
||||
|
||||
# Check that we have stopped at correct breakpoint.
|
||||
self.assertEqual(
|
||||
thread.frame[0].GetLineEntry().GetLine(),
|
||||
bp1.GetLocationAtIndex(0).GetAddress().GetLineEntry().GetLine(),
|
||||
"LLDB reported incorrect line number.",
|
||||
)
|
||||
|
||||
# Important to use SBProcess::Continue() instead of
|
||||
# self.runCmd('continue'), because the problem doesn't reproduce with
|
||||
# 'continue' command.
|
||||
process.Continue()
|
||||
|
||||
if self.TraceOn():
|
||||
print("Backtrace at the second breakpoint:")
|
||||
for f in thread.frames:
|
||||
print(f)
|
||||
# Check that we have stopped at the breakpoint
|
||||
self.assertEqual(
|
||||
thread.frame[0].GetLineEntry().GetLine(),
|
||||
bp2.GetLocationAtIndex(0).GetAddress().GetLineEntry().GetLine(),
|
||||
"LLDB reported incorrect line number.",
|
||||
)
|
||||
# Double-check with GetPCAddress()
|
||||
self.assertEqual(
|
||||
thread.frame[0].GetLineEntry().GetLine(),
|
||||
thread.frame[0].GetPCAddress().GetLineEntry().GetLine(),
|
||||
"LLDB reported incorrect line number.",
|
||||
)
|
||||
|
@ -1,3 +1,3 @@
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include Makefile.rules
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include Makefile.rules
|
||||
|
@ -1,35 +1,35 @@
|
||||
RUN: %build -n --verbose --arch=32 --mode=compile --compiler=any -o %t/foo.out foobar.c \
|
||||
RUN: | FileCheck --check-prefix=COMPILE %s
|
||||
|
||||
RUN: %build -n --verbose --arch=32 --mode=compile --compiler=any --outdir %t foo.c bar.c \
|
||||
RUN: | FileCheck --check-prefix=COMPILE-MULTI %s
|
||||
|
||||
RUN: %build -n --verbose --arch=32 --mode=link --compiler=any -o %t/foo.exe foobar.obj \
|
||||
RUN: | FileCheck --check-prefix=LINK %s
|
||||
|
||||
RUN: %build -n --verbose --arch=32 --mode=link --compiler=any -o %t/foobar.exe foo.obj bar.obj \
|
||||
RUN: | FileCheck --check-prefix=LINK-MULTI %s
|
||||
|
||||
RUN: %build -n --verbose --arch=32 --mode=compile-and-link --compiler=any -o %t/foobar.exe foobar.c \
|
||||
RUN: | FileCheck --check-prefix=BOTH %s
|
||||
|
||||
RUN: %build -n --verbose --arch=32 --mode=compile-and-link --compiler=any -o %t/foobar.exe foo.c bar.c \
|
||||
RUN: | FileCheck --check-prefix=BOTH-MULTI %s
|
||||
|
||||
|
||||
COMPILE: compiling foobar.c -> foo.out
|
||||
|
||||
COMPILE-MULTI: compiling foo.c -> foo.o{{(bj)?}}
|
||||
COMPILE-MULTI: compiling bar.c -> bar.o{{(bj)?}}
|
||||
|
||||
|
||||
LINK: linking foobar.obj -> foo.exe
|
||||
|
||||
LINK-MULTI: linking foo.obj+bar.obj -> foobar.exe
|
||||
|
||||
BOTH: compiling foobar.c -> [[OBJFOO:foobar.exe-foobar.o(bj)?]]
|
||||
BOTH: linking [[OBJFOO]] -> foobar.exe
|
||||
|
||||
BOTH-MULTI: compiling foo.c -> [[OBJFOO:foobar.exe-foo.o(bj)?]]
|
||||
BOTH-MULTI: compiling bar.c -> [[OBJBAR:foobar.exe-bar.o(bj)?]]
|
||||
BOTH-MULTI: linking [[OBJFOO]]+[[OBJBAR]] -> foobar.exe
|
||||
RUN: %build -n --verbose --arch=32 --mode=compile --compiler=any -o %t/foo.out foobar.c \
|
||||
RUN: | FileCheck --check-prefix=COMPILE %s
|
||||
|
||||
RUN: %build -n --verbose --arch=32 --mode=compile --compiler=any --outdir %t foo.c bar.c \
|
||||
RUN: | FileCheck --check-prefix=COMPILE-MULTI %s
|
||||
|
||||
RUN: %build -n --verbose --arch=32 --mode=link --compiler=any -o %t/foo.exe foobar.obj \
|
||||
RUN: | FileCheck --check-prefix=LINK %s
|
||||
|
||||
RUN: %build -n --verbose --arch=32 --mode=link --compiler=any -o %t/foobar.exe foo.obj bar.obj \
|
||||
RUN: | FileCheck --check-prefix=LINK-MULTI %s
|
||||
|
||||
RUN: %build -n --verbose --arch=32 --mode=compile-and-link --compiler=any -o %t/foobar.exe foobar.c \
|
||||
RUN: | FileCheck --check-prefix=BOTH %s
|
||||
|
||||
RUN: %build -n --verbose --arch=32 --mode=compile-and-link --compiler=any -o %t/foobar.exe foo.c bar.c \
|
||||
RUN: | FileCheck --check-prefix=BOTH-MULTI %s
|
||||
|
||||
|
||||
COMPILE: compiling foobar.c -> foo.out
|
||||
|
||||
COMPILE-MULTI: compiling foo.c -> foo.o{{(bj)?}}
|
||||
COMPILE-MULTI: compiling bar.c -> bar.o{{(bj)?}}
|
||||
|
||||
|
||||
LINK: linking foobar.obj -> foo.exe
|
||||
|
||||
LINK-MULTI: linking foo.obj+bar.obj -> foobar.exe
|
||||
|
||||
BOTH: compiling foobar.c -> [[OBJFOO:foobar.exe-foobar.o(bj)?]]
|
||||
BOTH: linking [[OBJFOO]] -> foobar.exe
|
||||
|
||||
BOTH-MULTI: compiling foo.c -> [[OBJFOO:foobar.exe-foo.o(bj)?]]
|
||||
BOTH-MULTI: compiling bar.c -> [[OBJBAR:foobar.exe-bar.o(bj)?]]
|
||||
BOTH-MULTI: linking [[OBJFOO]]+[[OBJBAR]] -> foobar.exe
|
||||
|
@ -1,32 +1,32 @@
|
||||
RUN: %build -n --verbose --arch=32 --mode=compile --compiler=any -o %t/foo.out foobar.c \
|
||||
RUN: | FileCheck %s
|
||||
RUN: %build -n --verbose --arch=32 --mode=compile --compiler=any --outdir %t foo.c bar.c \
|
||||
RUN: | FileCheck --check-prefix=MULTI-INPUT %s
|
||||
|
||||
|
||||
CHECK: Script Arguments:
|
||||
CHECK-NEXT: Arch: 32
|
||||
CHECK: Compiler: any
|
||||
CHECK: Outdir: {{.*}}script-args.test.tmp
|
||||
CHECK: Output: {{.*}}script-args.test.tmp{{.}}foo.out
|
||||
CHECK: Nodefaultlib: False
|
||||
CHECK: Opt: none
|
||||
CHECK: Mode: compile
|
||||
CHECK: Clean: True
|
||||
CHECK: Verbose: True
|
||||
CHECK: Dryrun: True
|
||||
CHECK: Inputs: foobar.c
|
||||
|
||||
MULTI-INPUT: Script Arguments:
|
||||
MULTI-INPUT-NEXT: Arch: 32
|
||||
MULTI-INPUT-NEXT: Compiler: any
|
||||
MULTI-INPUT-NEXT: Outdir: {{.*}}script-args.test.tmp
|
||||
MULTI-INPUT-NEXT: Output:
|
||||
MULTI-INPUT-NEXT: Nodefaultlib: False
|
||||
MULTI-INPUT-NEXT: Opt: none
|
||||
MULTI-INPUT-NEXT: Mode: compile
|
||||
MULTI-INPUT-NEXT: Clean: True
|
||||
MULTI-INPUT-NEXT: Verbose: True
|
||||
MULTI-INPUT-NEXT: Dryrun: True
|
||||
MULTI-INPUT-NEXT: Inputs: foo.c
|
||||
MULTI-INPUT-NEXT: bar.c
|
||||
RUN: %build -n --verbose --arch=32 --mode=compile --compiler=any -o %t/foo.out foobar.c \
|
||||
RUN: | FileCheck %s
|
||||
RUN: %build -n --verbose --arch=32 --mode=compile --compiler=any --outdir %t foo.c bar.c \
|
||||
RUN: | FileCheck --check-prefix=MULTI-INPUT %s
|
||||
|
||||
|
||||
CHECK: Script Arguments:
|
||||
CHECK-NEXT: Arch: 32
|
||||
CHECK: Compiler: any
|
||||
CHECK: Outdir: {{.*}}script-args.test.tmp
|
||||
CHECK: Output: {{.*}}script-args.test.tmp{{.}}foo.out
|
||||
CHECK: Nodefaultlib: False
|
||||
CHECK: Opt: none
|
||||
CHECK: Mode: compile
|
||||
CHECK: Clean: True
|
||||
CHECK: Verbose: True
|
||||
CHECK: Dryrun: True
|
||||
CHECK: Inputs: foobar.c
|
||||
|
||||
MULTI-INPUT: Script Arguments:
|
||||
MULTI-INPUT-NEXT: Arch: 32
|
||||
MULTI-INPUT-NEXT: Compiler: any
|
||||
MULTI-INPUT-NEXT: Outdir: {{.*}}script-args.test.tmp
|
||||
MULTI-INPUT-NEXT: Output:
|
||||
MULTI-INPUT-NEXT: Nodefaultlib: False
|
||||
MULTI-INPUT-NEXT: Opt: none
|
||||
MULTI-INPUT-NEXT: Mode: compile
|
||||
MULTI-INPUT-NEXT: Clean: True
|
||||
MULTI-INPUT-NEXT: Verbose: True
|
||||
MULTI-INPUT-NEXT: Dryrun: True
|
||||
MULTI-INPUT-NEXT: Inputs: foo.c
|
||||
MULTI-INPUT-NEXT: bar.c
|
||||
|
@ -1,49 +1,49 @@
|
||||
REQUIRES: lld, system-windows
|
||||
|
||||
RUN: %build -n --verbose --arch=32 --compiler=clang-cl --mode=compile-and-link -o %t/foo.exe foobar.c \
|
||||
RUN: | FileCheck --check-prefix=CHECK-32 %s
|
||||
|
||||
RUN: %build -n --verbose --arch=64 --compiler=clang-cl --mode=compile-and-link -o %t/foo.exe foobar.c \
|
||||
RUN: | FileCheck --check-prefix=CHECK-64 %s
|
||||
|
||||
CHECK-32: Script Arguments:
|
||||
CHECK-32: Arch: 32
|
||||
CHECK-32: Compiler: clang-cl
|
||||
CHECK-32: Outdir: {{.*}}
|
||||
CHECK-32: Output: {{.*}}toolchain-clang-cl.test.tmp\foo.exe
|
||||
CHECK-32: Nodefaultlib: False
|
||||
CHECK-32: Opt: none
|
||||
CHECK-32: Mode: compile
|
||||
CHECK-32: Clean: True
|
||||
CHECK-32: Verbose: True
|
||||
CHECK-32: Dryrun: True
|
||||
CHECK-32: Inputs: foobar.c
|
||||
CHECK-32: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foobar.ilk
|
||||
CHECK-32: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.exe-foobar.obj
|
||||
CHECK-32: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.pdb
|
||||
CHECK-32: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.exe
|
||||
CHECK-32: compiling foobar.c -> foo.exe-foobar.obj
|
||||
CHECK-32: {{.*}}clang-cl{{(\.EXE)?}} -m32
|
||||
CHECK-32: linking foo.exe-foobar.obj -> foo.exe
|
||||
CHECK-32: {{.*}}lld-link{{(\.EXE)?}}
|
||||
|
||||
CHECK-64: Script Arguments:
|
||||
CHECK-64: Arch: 64
|
||||
CHECK-64: Compiler: clang-cl
|
||||
CHECK-64: Outdir: {{.*}}
|
||||
CHECK-64: Output: {{.*}}toolchain-clang-cl.test.tmp\foo.exe
|
||||
CHECK-64: Nodefaultlib: False
|
||||
CHECK-64: Opt: none
|
||||
CHECK-64: Mode: compile
|
||||
CHECK-64: Clean: True
|
||||
CHECK-64: Verbose: True
|
||||
CHECK-64: Dryrun: True
|
||||
CHECK-64: Inputs: foobar.c
|
||||
CHECK-64: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foobar.ilk
|
||||
CHECK-64: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.exe-foobar.obj
|
||||
CHECK-64: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.pdb
|
||||
CHECK-64: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.exe
|
||||
CHECK-64: compiling foobar.c -> foo.exe-foobar.obj
|
||||
CHECK-64: {{.*}}clang-cl{{(\.EXE)?}} -m64
|
||||
CHECK-64: linking foo.exe-foobar.obj -> foo.exe
|
||||
CHECK-64: {{.*}}lld-link{{(\.EXE)?}}
|
||||
REQUIRES: lld, system-windows
|
||||
|
||||
RUN: %build -n --verbose --arch=32 --compiler=clang-cl --mode=compile-and-link -o %t/foo.exe foobar.c \
|
||||
RUN: | FileCheck --check-prefix=CHECK-32 %s
|
||||
|
||||
RUN: %build -n --verbose --arch=64 --compiler=clang-cl --mode=compile-and-link -o %t/foo.exe foobar.c \
|
||||
RUN: | FileCheck --check-prefix=CHECK-64 %s
|
||||
|
||||
CHECK-32: Script Arguments:
|
||||
CHECK-32: Arch: 32
|
||||
CHECK-32: Compiler: clang-cl
|
||||
CHECK-32: Outdir: {{.*}}
|
||||
CHECK-32: Output: {{.*}}toolchain-clang-cl.test.tmp\foo.exe
|
||||
CHECK-32: Nodefaultlib: False
|
||||
CHECK-32: Opt: none
|
||||
CHECK-32: Mode: compile
|
||||
CHECK-32: Clean: True
|
||||
CHECK-32: Verbose: True
|
||||
CHECK-32: Dryrun: True
|
||||
CHECK-32: Inputs: foobar.c
|
||||
CHECK-32: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foobar.ilk
|
||||
CHECK-32: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.exe-foobar.obj
|
||||
CHECK-32: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.pdb
|
||||
CHECK-32: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.exe
|
||||
CHECK-32: compiling foobar.c -> foo.exe-foobar.obj
|
||||
CHECK-32: {{.*}}clang-cl{{(\.EXE)?}} -m32
|
||||
CHECK-32: linking foo.exe-foobar.obj -> foo.exe
|
||||
CHECK-32: {{.*}}lld-link{{(\.EXE)?}}
|
||||
|
||||
CHECK-64: Script Arguments:
|
||||
CHECK-64: Arch: 64
|
||||
CHECK-64: Compiler: clang-cl
|
||||
CHECK-64: Outdir: {{.*}}
|
||||
CHECK-64: Output: {{.*}}toolchain-clang-cl.test.tmp\foo.exe
|
||||
CHECK-64: Nodefaultlib: False
|
||||
CHECK-64: Opt: none
|
||||
CHECK-64: Mode: compile
|
||||
CHECK-64: Clean: True
|
||||
CHECK-64: Verbose: True
|
||||
CHECK-64: Dryrun: True
|
||||
CHECK-64: Inputs: foobar.c
|
||||
CHECK-64: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foobar.ilk
|
||||
CHECK-64: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.exe-foobar.obj
|
||||
CHECK-64: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.pdb
|
||||
CHECK-64: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.exe
|
||||
CHECK-64: compiling foobar.c -> foo.exe-foobar.obj
|
||||
CHECK-64: {{.*}}clang-cl{{(\.EXE)?}} -m64
|
||||
CHECK-64: linking foo.exe-foobar.obj -> foo.exe
|
||||
CHECK-64: {{.*}}lld-link{{(\.EXE)?}}
|
||||
|
@ -1,40 +1,40 @@
|
||||
|
||||
// nodefaultlib build: cl -Zi sigsegv.cpp /link /nodefaultlib
|
||||
|
||||
#ifdef USE_CRT
|
||||
#include <stdio.h>
|
||||
#else
|
||||
int main();
|
||||
extern "C"
|
||||
{
|
||||
int _fltused;
|
||||
void mainCRTStartup() { main(); }
|
||||
void printf(const char*, ...) {}
|
||||
}
|
||||
#endif
|
||||
|
||||
void crash(bool crash_self)
|
||||
{
|
||||
printf("Before...\n");
|
||||
if(crash_self)
|
||||
{
|
||||
printf("Crashing in 3, 2, 1 ...\n");
|
||||
*(volatile int*)nullptr = 0;
|
||||
}
|
||||
printf("After...\n");
|
||||
}
|
||||
|
||||
int foo(int x, float y, const char* msg)
|
||||
{
|
||||
bool flag = x > y;
|
||||
if(flag)
|
||||
printf("x = %d, y = %f, msg = %s\n", x, y, msg);
|
||||
crash(flag);
|
||||
return x << 1;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
foo(10, 3.14, "testing");
|
||||
}
|
||||
|
||||
|
||||
// nodefaultlib build: cl -Zi sigsegv.cpp /link /nodefaultlib
|
||||
|
||||
#ifdef USE_CRT
|
||||
#include <stdio.h>
|
||||
#else
|
||||
int main();
|
||||
extern "C"
|
||||
{
|
||||
int _fltused;
|
||||
void mainCRTStartup() { main(); }
|
||||
void printf(const char*, ...) {}
|
||||
}
|
||||
#endif
|
||||
|
||||
void crash(bool crash_self)
|
||||
{
|
||||
printf("Before...\n");
|
||||
if(crash_self)
|
||||
{
|
||||
printf("Crashing in 3, 2, 1 ...\n");
|
||||
*(volatile int*)nullptr = 0;
|
||||
}
|
||||
printf("After...\n");
|
||||
}
|
||||
|
||||
int foo(int x, float y, const char* msg)
|
||||
{
|
||||
bool flag = x > y;
|
||||
if(flag)
|
||||
printf("x = %d, y = %f, msg = %s\n", x, y, msg);
|
||||
crash(flag);
|
||||
return x << 1;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
foo(10, 3.14, "testing");
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
br set -p BP_bar -f inline_sites_live.cpp
|
||||
br set -p BP_foo -f inline_sites_live.cpp
|
||||
run
|
||||
expression param
|
||||
continue
|
||||
expression param
|
||||
expression local
|
||||
br set -p BP_bar -f inline_sites_live.cpp
|
||||
br set -p BP_foo -f inline_sites_live.cpp
|
||||
run
|
||||
expression param
|
||||
continue
|
||||
expression param
|
||||
expression local
|
||||
|
@ -1,35 +1,35 @@
|
||||
image lookup -a 0x140001000 -v
|
||||
image lookup -a 0x140001003 -v
|
||||
image lookup -a 0x140001006 -v
|
||||
|
||||
image lookup -a 0x140001011 -v
|
||||
image lookup -a 0x140001017 -v
|
||||
image lookup -a 0x140001019 -v
|
||||
image lookup -a 0x14000101e -v
|
||||
image lookup -a 0x14000102c -v
|
||||
|
||||
image lookup -a 0x140001031 -v
|
||||
image lookup -a 0x140001032 -v
|
||||
image lookup -a 0x140001033 -v
|
||||
image lookup -a 0x140001034 -v
|
||||
image lookup -a 0x140001035 -v
|
||||
image lookup -a 0x140001036 -v
|
||||
image lookup -a 0x140001037 -v
|
||||
image lookup -a 0x14000103b -v
|
||||
image lookup -a 0x14000103d -v
|
||||
image lookup -a 0x14000103f -v
|
||||
image lookup -a 0x140001041 -v
|
||||
image lookup -a 0x140001043 -v
|
||||
image lookup -a 0x140001045 -v
|
||||
image lookup -a 0x140001046 -v
|
||||
image lookup -a 0x140001047 -v
|
||||
image lookup -a 0x140001048 -v
|
||||
image lookup -a 0x140001049 -v
|
||||
image lookup -a 0x14000104a -v
|
||||
image lookup -a 0x14000104b -v
|
||||
image lookup -a 0x14000104c -v
|
||||
image lookup -a 0x14000104e -v
|
||||
image lookup -a 0x14000104f -v
|
||||
image lookup -a 0x140001050 -v
|
||||
image lookup -a 0x140001051 -v
|
||||
exit
|
||||
image lookup -a 0x140001000 -v
|
||||
image lookup -a 0x140001003 -v
|
||||
image lookup -a 0x140001006 -v
|
||||
|
||||
image lookup -a 0x140001011 -v
|
||||
image lookup -a 0x140001017 -v
|
||||
image lookup -a 0x140001019 -v
|
||||
image lookup -a 0x14000101e -v
|
||||
image lookup -a 0x14000102c -v
|
||||
|
||||
image lookup -a 0x140001031 -v
|
||||
image lookup -a 0x140001032 -v
|
||||
image lookup -a 0x140001033 -v
|
||||
image lookup -a 0x140001034 -v
|
||||
image lookup -a 0x140001035 -v
|
||||
image lookup -a 0x140001036 -v
|
||||
image lookup -a 0x140001037 -v
|
||||
image lookup -a 0x14000103b -v
|
||||
image lookup -a 0x14000103d -v
|
||||
image lookup -a 0x14000103f -v
|
||||
image lookup -a 0x140001041 -v
|
||||
image lookup -a 0x140001043 -v
|
||||
image lookup -a 0x140001045 -v
|
||||
image lookup -a 0x140001046 -v
|
||||
image lookup -a 0x140001047 -v
|
||||
image lookup -a 0x140001048 -v
|
||||
image lookup -a 0x140001049 -v
|
||||
image lookup -a 0x14000104a -v
|
||||
image lookup -a 0x14000104b -v
|
||||
image lookup -a 0x14000104c -v
|
||||
image lookup -a 0x14000104e -v
|
||||
image lookup -a 0x14000104f -v
|
||||
image lookup -a 0x140001050 -v
|
||||
image lookup -a 0x140001051 -v
|
||||
exit
|
||||
|
@ -1,4 +1,4 @@
|
||||
image lookup -type A
|
||||
image lookup -type B
|
||||
|
||||
image lookup -type A
|
||||
image lookup -type B
|
||||
|
||||
quit
|
@ -1,2 +1,2 @@
|
||||
image lookup -a 0x40102f -v
|
||||
quit
|
||||
image lookup -a 0x40102f -v
|
||||
quit
|
||||
|
@ -113,9 +113,9 @@ auto incomplete = &three<Incomplete*, Incomplete**, const Incomplete*>;
|
||||
// CHECK: |-CXXRecordDecl {{.*}} union U
|
||||
// CHECK: |-EnumDecl {{.*}} E
|
||||
// CHECK: |-CXXRecordDecl {{.*}} struct S
|
||||
// CHECK: |-VarDecl {{.*}} a 'S (*)(C *, U &, E &&)'
|
||||
// CHECK: |-VarDecl {{.*}} b 'E (*)(const S *, const C &, const U &&)'
|
||||
// CHECK: |-VarDecl {{.*}} c 'U (*)(volatile E *, volatile S &, volatile C &&)'
|
||||
// CHECK: |-VarDecl {{.*}} a 'S (*)(C *, U &, E &&)'
|
||||
// CHECK: |-VarDecl {{.*}} b 'E (*)(const S *, const C &, const U &&)'
|
||||
// CHECK: |-VarDecl {{.*}} c 'U (*)(volatile E *, volatile S &, volatile C &&)'
|
||||
// CHECK: |-VarDecl {{.*}} d 'C (*)(const volatile U *, const volatile E &, const volatile S &&)'
|
||||
// CHECK: |-CXXRecordDecl {{.*}} struct B
|
||||
// CHECK: | `-CXXRecordDecl {{.*}} struct A
|
||||
@ -125,14 +125,14 @@ auto incomplete = &three<Incomplete*, Incomplete**, const Incomplete*>;
|
||||
// CHECK: | | `-CXXRecordDecl {{.*}} struct S
|
||||
// CHECK: | `-NamespaceDecl {{.*}} B
|
||||
// CHECK: | `-CXXRecordDecl {{.*}} struct S
|
||||
// CHECK: |-VarDecl {{.*}} e 'A::B::S *(*)(B::A::S *, A::C::S &)'
|
||||
// CHECK: |-VarDecl {{.*}} f 'A::C::S &(*)(A::B::S *, B::A::S *)'
|
||||
// CHECK: |-VarDecl {{.*}} e 'A::B::S *(*)(B::A::S *, A::C::S &)'
|
||||
// CHECK: |-VarDecl {{.*}} f 'A::C::S &(*)(A::B::S *, B::A::S *)'
|
||||
// CHECK: |-VarDecl {{.*}} g 'B::A::S *(*)(A::C::S &, A::B::S *)'
|
||||
// CHECK: |-CXXRecordDecl {{.*}} struct TC<int>
|
||||
// CHECK: |-CXXRecordDecl {{.*}} struct TC<TC<int>>
|
||||
// CHECK: |-CXXRecordDecl {{.*}} struct TC<A::B::S>
|
||||
// CHECK: |-CXXRecordDecl {{.*}} struct TC<void>
|
||||
// CHECK: |-VarDecl {{.*}} h 'TC<void> (*)(TC<int>, TC<TC<int>>, TC<A::B::S>)'
|
||||
// CHECK: |-VarDecl {{.*}} h 'TC<void> (*)(TC<int>, TC<TC<int>>, TC<A::B::S>)'
|
||||
// CHECK: |-VarDecl {{.*}} i 'A::B::S (*)()'
|
||||
// CHECK: |-CXXRecordDecl {{.*}} struct Incomplete
|
||||
// CHECK: `-VarDecl {{.*}} incomplete 'Incomplete *(*)(Incomplete **, const Incomplete *)'
|
||||
|
@ -1,34 +1,34 @@
|
||||
// clang-format off
|
||||
// REQUIRES: system-windows
|
||||
|
||||
// RUN: %build -o %t.exe -- %s
|
||||
// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
|
||||
// RUN: %p/Inputs/inline_sites_live.lldbinit 2>&1 | FileCheck %s
|
||||
|
||||
void use(int) {}
|
||||
|
||||
void __attribute__((always_inline)) bar(int param) {
|
||||
use(param); // BP_bar
|
||||
}
|
||||
|
||||
void __attribute__((always_inline)) foo(int param) {
|
||||
int local = param+1;
|
||||
bar(local);
|
||||
use(param);
|
||||
use(local); // BP_foo
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
foo(argc);
|
||||
}
|
||||
|
||||
// CHECK: * thread #1, stop reason = breakpoint 1
|
||||
// CHECK-NEXT: frame #0: {{.*}}`main [inlined] bar(param=2)
|
||||
// CHECK: (lldb) expression param
|
||||
// CHECK-NEXT: (int) $0 = 2
|
||||
// CHECK: * thread #1, stop reason = breakpoint 2
|
||||
// CHECK-NEXT: frame #0: {{.*}}`main [inlined] foo(param=1)
|
||||
// CHECK: (lldb) expression param
|
||||
// CHECK-NEXT: (int) $1 = 1
|
||||
// CHECK-NEXT: (lldb) expression local
|
||||
// CHECK-NEXT: (int) $2 = 2
|
||||
// clang-format off
|
||||
// REQUIRES: system-windows
|
||||
|
||||
// RUN: %build -o %t.exe -- %s
|
||||
// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
|
||||
// RUN: %p/Inputs/inline_sites_live.lldbinit 2>&1 | FileCheck %s
|
||||
|
||||
void use(int) {}
|
||||
|
||||
void __attribute__((always_inline)) bar(int param) {
|
||||
use(param); // BP_bar
|
||||
}
|
||||
|
||||
void __attribute__((always_inline)) foo(int param) {
|
||||
int local = param+1;
|
||||
bar(local);
|
||||
use(param);
|
||||
use(local); // BP_foo
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
foo(argc);
|
||||
}
|
||||
|
||||
// CHECK: * thread #1, stop reason = breakpoint 1
|
||||
// CHECK-NEXT: frame #0: {{.*}}`main [inlined] bar(param=2)
|
||||
// CHECK: (lldb) expression param
|
||||
// CHECK-NEXT: (int) $0 = 2
|
||||
// CHECK: * thread #1, stop reason = breakpoint 2
|
||||
// CHECK-NEXT: frame #0: {{.*}}`main [inlined] foo(param=1)
|
||||
// CHECK: (lldb) expression param
|
||||
// CHECK-NEXT: (int) $1 = 1
|
||||
// CHECK-NEXT: (lldb) expression local
|
||||
// CHECK-NEXT: (int) $2 = 2
|
||||
|
@ -1,46 +1,46 @@
|
||||
// clang-format off
|
||||
|
||||
// RUN: %build -o %t.exe -- %s
|
||||
// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
|
||||
// RUN: %p/Inputs/lookup-by-types.lldbinit 2>&1 | FileCheck %s
|
||||
|
||||
class B;
|
||||
class A {
|
||||
public:
|
||||
static const A constA;
|
||||
static A a;
|
||||
static B b;
|
||||
int val = 1;
|
||||
};
|
||||
class B {
|
||||
public:
|
||||
static A a;
|
||||
int val = 2;
|
||||
};
|
||||
A varA;
|
||||
B varB;
|
||||
const A A::constA = varA;
|
||||
A A::a = varA;
|
||||
B A::b = varB;
|
||||
A B::a = varA;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
return varA.val + varB.val;
|
||||
}
|
||||
|
||||
// CHECK: image lookup -type A
|
||||
// CHECK-NEXT: 1 match found in {{.*}}.exe
|
||||
// CHECK-NEXT: compiler_type = "class A {
|
||||
// CHECK-NEXT: static const A constA;
|
||||
// CHECK-NEXT: static A a;
|
||||
// CHECK-NEXT: static B b;
|
||||
// CHECK-NEXT: public:
|
||||
// CHECK-NEXT: int val;
|
||||
// CHECK-NEXT: }"
|
||||
// CHECK: image lookup -type B
|
||||
// CHECK-NEXT: 1 match found in {{.*}}.exe
|
||||
// CHECK-NEXT: compiler_type = "class B {
|
||||
// CHECK-NEXT: static A a;
|
||||
// CHECK-NEXT: public:
|
||||
// CHECK-NEXT: int val;
|
||||
// CHECK-NEXT: }"
|
||||
// clang-format off
|
||||
|
||||
// RUN: %build -o %t.exe -- %s
|
||||
// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
|
||||
// RUN: %p/Inputs/lookup-by-types.lldbinit 2>&1 | FileCheck %s
|
||||
|
||||
class B;
|
||||
class A {
|
||||
public:
|
||||
static const A constA;
|
||||
static A a;
|
||||
static B b;
|
||||
int val = 1;
|
||||
};
|
||||
class B {
|
||||
public:
|
||||
static A a;
|
||||
int val = 2;
|
||||
};
|
||||
A varA;
|
||||
B varB;
|
||||
const A A::constA = varA;
|
||||
A A::a = varA;
|
||||
B A::b = varB;
|
||||
A B::a = varA;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
return varA.val + varB.val;
|
||||
}
|
||||
|
||||
// CHECK: image lookup -type A
|
||||
// CHECK-NEXT: 1 match found in {{.*}}.exe
|
||||
// CHECK-NEXT: compiler_type = "class A {
|
||||
// CHECK-NEXT: static const A constA;
|
||||
// CHECK-NEXT: static A a;
|
||||
// CHECK-NEXT: static B b;
|
||||
// CHECK-NEXT: public:
|
||||
// CHECK-NEXT: int val;
|
||||
// CHECK-NEXT: }"
|
||||
// CHECK: image lookup -type B
|
||||
// CHECK-NEXT: 1 match found in {{.*}}.exe
|
||||
// CHECK-NEXT: compiler_type = "class B {
|
||||
// CHECK-NEXT: static A a;
|
||||
// CHECK-NEXT: public:
|
||||
// CHECK-NEXT: int val;
|
||||
// CHECK-NEXT: }"
|
||||
|
@ -1,10 +1,10 @@
|
||||
add_lldb_unittest(LLDBBreakpointTests
|
||||
BreakpointIDTest.cpp
|
||||
WatchpointAlgorithmsTests.cpp
|
||||
|
||||
LINK_LIBS
|
||||
lldbBreakpoint
|
||||
lldbCore
|
||||
LINK_COMPONENTS
|
||||
Support
|
||||
)
|
||||
add_lldb_unittest(LLDBBreakpointTests
|
||||
BreakpointIDTest.cpp
|
||||
WatchpointAlgorithmsTests.cpp
|
||||
|
||||
LINK_LIBS
|
||||
lldbBreakpoint
|
||||
lldbCore
|
||||
LINK_COMPONENTS
|
||||
Support
|
||||
)
|
||||
|
@ -1,63 +1,63 @@
|
||||
//===- FormatVariadicBM.cpp - formatv() benchmark ---------- --------------===//
|
||||
//
|
||||
// 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 "benchmark/benchmark.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace std;
|
||||
|
||||
// Generate a list of format strings that have `NumReplacements` replacements
|
||||
// by permuting the replacements and some literal text.
|
||||
static vector<string> getFormatStrings(int NumReplacements) {
|
||||
vector<string> Components;
|
||||
for (int I = 0; I < NumReplacements; I++)
|
||||
Components.push_back("{" + to_string(I) + "}");
|
||||
// Intersperse these with some other literal text (_).
|
||||
const string_view Literal = "____";
|
||||
for (char C : Literal)
|
||||
Components.push_back(string(1, C));
|
||||
|
||||
vector<string> Formats;
|
||||
do {
|
||||
string Concat;
|
||||
for (const string &C : Components)
|
||||
Concat += C;
|
||||
Formats.emplace_back(Concat);
|
||||
} while (next_permutation(Components.begin(), Components.end()));
|
||||
return Formats;
|
||||
}
|
||||
|
||||
// Generate the set of formats to exercise outside the benchmark code.
|
||||
static const vector<vector<string>> Formats = {
|
||||
getFormatStrings(1), getFormatStrings(2), getFormatStrings(3),
|
||||
getFormatStrings(4), getFormatStrings(5),
|
||||
};
|
||||
|
||||
// Benchmark formatv() for a variety of format strings and 1-5 replacements.
|
||||
static void BM_FormatVariadic(benchmark::State &state) {
|
||||
for (auto _ : state) {
|
||||
for (const string &Fmt : Formats[0])
|
||||
formatv(Fmt.c_str(), 1).str();
|
||||
for (const string &Fmt : Formats[1])
|
||||
formatv(Fmt.c_str(), 1, 2).str();
|
||||
for (const string &Fmt : Formats[2])
|
||||
formatv(Fmt.c_str(), 1, 2, 3).str();
|
||||
for (const string &Fmt : Formats[3])
|
||||
formatv(Fmt.c_str(), 1, 2, 3, 4).str();
|
||||
for (const string &Fmt : Formats[4])
|
||||
formatv(Fmt.c_str(), 1, 2, 3, 4, 5).str();
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK(BM_FormatVariadic);
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
//===- FormatVariadicBM.cpp - formatv() benchmark ---------- --------------===//
|
||||
//
|
||||
// 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 "benchmark/benchmark.h"
|
||||
#include "llvm/Support/FormatVariadic.h"
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace std;
|
||||
|
||||
// Generate a list of format strings that have `NumReplacements` replacements
|
||||
// by permuting the replacements and some literal text.
|
||||
static vector<string> getFormatStrings(int NumReplacements) {
|
||||
vector<string> Components;
|
||||
for (int I = 0; I < NumReplacements; I++)
|
||||
Components.push_back("{" + to_string(I) + "}");
|
||||
// Intersperse these with some other literal text (_).
|
||||
const string_view Literal = "____";
|
||||
for (char C : Literal)
|
||||
Components.push_back(string(1, C));
|
||||
|
||||
vector<string> Formats;
|
||||
do {
|
||||
string Concat;
|
||||
for (const string &C : Components)
|
||||
Concat += C;
|
||||
Formats.emplace_back(Concat);
|
||||
} while (next_permutation(Components.begin(), Components.end()));
|
||||
return Formats;
|
||||
}
|
||||
|
||||
// Generate the set of formats to exercise outside the benchmark code.
|
||||
static const vector<vector<string>> Formats = {
|
||||
getFormatStrings(1), getFormatStrings(2), getFormatStrings(3),
|
||||
getFormatStrings(4), getFormatStrings(5),
|
||||
};
|
||||
|
||||
// Benchmark formatv() for a variety of format strings and 1-5 replacements.
|
||||
static void BM_FormatVariadic(benchmark::State &state) {
|
||||
for (auto _ : state) {
|
||||
for (const string &Fmt : Formats[0])
|
||||
formatv(Fmt.c_str(), 1).str();
|
||||
for (const string &Fmt : Formats[1])
|
||||
formatv(Fmt.c_str(), 1, 2).str();
|
||||
for (const string &Fmt : Formats[2])
|
||||
formatv(Fmt.c_str(), 1, 2, 3).str();
|
||||
for (const string &Fmt : Formats[3])
|
||||
formatv(Fmt.c_str(), 1, 2, 3, 4).str();
|
||||
for (const string &Fmt : Formats[4])
|
||||
formatv(Fmt.c_str(), 1, 2, 3, 4, 5).str();
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK(BM_FormatVariadic);
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
|
@ -1,50 +1,50 @@
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace Intrinsic;
|
||||
|
||||
// Benchmark intrinsic lookup from a variety of targets.
|
||||
static void BM_GetIntrinsicForClangBuiltin(benchmark::State &state) {
|
||||
static const char *Builtins[] = {
|
||||
"__builtin_adjust_trampoline",
|
||||
"__builtin_trap",
|
||||
"__builtin_arm_ttest",
|
||||
"__builtin_amdgcn_cubetc",
|
||||
"__builtin_amdgcn_udot2",
|
||||
"__builtin_arm_stc",
|
||||
"__builtin_bpf_compare",
|
||||
"__builtin_HEXAGON_A2_max",
|
||||
"__builtin_lasx_xvabsd_b",
|
||||
"__builtin_mips_dlsa",
|
||||
"__nvvm_floor_f",
|
||||
"__builtin_altivec_vslb",
|
||||
"__builtin_r600_read_tgid_x",
|
||||
"__builtin_riscv_aes64im",
|
||||
"__builtin_s390_vcksm",
|
||||
"__builtin_ve_vl_pvfmksge_Mvl",
|
||||
"__builtin_ia32_axor64",
|
||||
"__builtin_bitrev",
|
||||
};
|
||||
static const char *Targets[] = {"", "aarch64", "amdgcn", "mips",
|
||||
"nvvm", "r600", "riscv"};
|
||||
|
||||
for (auto _ : state) {
|
||||
for (auto Builtin : Builtins)
|
||||
for (auto Target : Targets)
|
||||
getIntrinsicForClangBuiltin(Target, Builtin);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
BM_GetIntrinsicForClangBuiltinHexagonFirst(benchmark::State &state) {
|
||||
// Exercise the worst case by looking for the first builtin for a target
|
||||
// that has a lot of builtins.
|
||||
for (auto _ : state)
|
||||
getIntrinsicForClangBuiltin("hexagon", "__builtin_HEXAGON_A2_abs");
|
||||
}
|
||||
|
||||
BENCHMARK(BM_GetIntrinsicForClangBuiltin);
|
||||
BENCHMARK(BM_GetIntrinsicForClangBuiltinHexagonFirst);
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace Intrinsic;
|
||||
|
||||
// Benchmark intrinsic lookup from a variety of targets.
|
||||
static void BM_GetIntrinsicForClangBuiltin(benchmark::State &state) {
|
||||
static const char *Builtins[] = {
|
||||
"__builtin_adjust_trampoline",
|
||||
"__builtin_trap",
|
||||
"__builtin_arm_ttest",
|
||||
"__builtin_amdgcn_cubetc",
|
||||
"__builtin_amdgcn_udot2",
|
||||
"__builtin_arm_stc",
|
||||
"__builtin_bpf_compare",
|
||||
"__builtin_HEXAGON_A2_max",
|
||||
"__builtin_lasx_xvabsd_b",
|
||||
"__builtin_mips_dlsa",
|
||||
"__nvvm_floor_f",
|
||||
"__builtin_altivec_vslb",
|
||||
"__builtin_r600_read_tgid_x",
|
||||
"__builtin_riscv_aes64im",
|
||||
"__builtin_s390_vcksm",
|
||||
"__builtin_ve_vl_pvfmksge_Mvl",
|
||||
"__builtin_ia32_axor64",
|
||||
"__builtin_bitrev",
|
||||
};
|
||||
static const char *Targets[] = {"", "aarch64", "amdgcn", "mips",
|
||||
"nvvm", "r600", "riscv"};
|
||||
|
||||
for (auto _ : state) {
|
||||
for (auto Builtin : Builtins)
|
||||
for (auto Target : Targets)
|
||||
getIntrinsicForClangBuiltin(Target, Builtin);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
BM_GetIntrinsicForClangBuiltinHexagonFirst(benchmark::State &state) {
|
||||
// Exercise the worst case by looking for the first builtin for a target
|
||||
// that has a lot of builtins.
|
||||
for (auto _ : state)
|
||||
getIntrinsicForClangBuiltin("hexagon", "__builtin_HEXAGON_A2_abs");
|
||||
}
|
||||
|
||||
BENCHMARK(BM_GetIntrinsicForClangBuiltin);
|
||||
BENCHMARK(BM_GetIntrinsicForClangBuiltinHexagonFirst);
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
|
@ -1,30 +1,30 @@
|
||||
//===- GetIntrinsicInfoTableEntries.cpp - IIT signature benchmark ---------===//
|
||||
//
|
||||
// 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 "benchmark/benchmark.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace Intrinsic;
|
||||
|
||||
static void BM_GetIntrinsicInfoTableEntries(benchmark::State &state) {
|
||||
SmallVector<IITDescriptor> Table;
|
||||
for (auto _ : state) {
|
||||
for (ID ID = 1; ID < num_intrinsics; ++ID) {
|
||||
// This makes sure the vector does not keep growing, as well as after the
|
||||
// first iteration does not result in additional allocations.
|
||||
Table.clear();
|
||||
getIntrinsicInfoTableEntries(ID, Table);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK(BM_GetIntrinsicInfoTableEntries);
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
//===- GetIntrinsicInfoTableEntries.cpp - IIT signature benchmark ---------===//
|
||||
//
|
||||
// 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 "benchmark/benchmark.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace Intrinsic;
|
||||
|
||||
static void BM_GetIntrinsicInfoTableEntries(benchmark::State &state) {
|
||||
SmallVector<IITDescriptor> Table;
|
||||
for (auto _ : state) {
|
||||
for (ID ID = 1; ID < num_intrinsics; ++ID) {
|
||||
// This makes sure the vector does not keep growing, as well as after the
|
||||
// first iteration does not result in additional allocations.
|
||||
Table.clear();
|
||||
getIntrinsicInfoTableEntries(ID, Table);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK(BM_GetIntrinsicInfoTableEntries);
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
|
160
llvm/docs/_static/LoopOptWG_invite.ics
vendored
160
llvm/docs/_static/LoopOptWG_invite.ics
vendored
@ -1,80 +1,80 @@
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
||||
VERSION:2.0
|
||||
CALSCALE:GREGORIAN
|
||||
METHOD:PUBLISH
|
||||
X-WR-CALNAME:LLVM Loop Optimization Discussion
|
||||
X-WR-TIMEZONE:Europe/Berlin
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/New_York
|
||||
X-LIC-LOCATION:America/New_York
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:-0500
|
||||
TZOFFSETTO:-0400
|
||||
TZNAME:EDT
|
||||
DTSTART:19700308T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
|
||||
END:DAYLIGHT
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0400
|
||||
TZOFFSETTO:-0500
|
||||
TZNAME:EST
|
||||
DTSTART:19701101T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
BEGIN:VEVENT
|
||||
DTSTART;TZID=America/New_York:20240904T110000
|
||||
DTEND;TZID=America/New_York:20240904T120000
|
||||
RRULE:FREQ=MONTHLY;BYDAY=1WE
|
||||
DTSTAMP:20240821T160951Z
|
||||
UID:58h3f0kd3aooohmeii0johh23c@google.com
|
||||
X-GOOGLE-CONFERENCE:https://meet.google.com/fmz-gspu-odg
|
||||
CREATED:20240821T151507Z
|
||||
DESCRIPTION:LLVM Loop Optimization Discussion<br>Video call link: <a href="
|
||||
https://meet.google.com/fmz-gspu-odg" target="_blank">https://meet.google.c
|
||||
om/fmz-gspu-odg</a><br>Agenda/Minutes/Discussion: <a href="https://docs.goo
|
||||
gle.com/document/d/1sdzoyB11s0ccTZ3fobqctDpgJmRoFcz0sviKxqczs4g/edit?usp=sh
|
||||
aring" class="pastedDriveLink-0">https://docs.google.com/document/d/1sdzoyB
|
||||
11s0ccTZ3fobqctDpgJmRoFcz0sviKxqczs4g/edit?usp=sharing</a>\n\n-::~:~::~:~:~
|
||||
:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~::~:~::-\
|
||||
nJoin with Google Meet: https://meet.google.com/fmz-gspu-odg\nOr dial: (DE)
|
||||
+49 40 8081617343 PIN: 948106286#\nMore phone numbers: https://tel.meet/fm
|
||||
z-gspu-odg?pin=6273693382184&hs=7\n\nLearn more about Meet at: https://supp
|
||||
ort.google.com/a/users/answer/9282720\n\nPlease do not edit this section.\n
|
||||
-::~:~::~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~
|
||||
:~:~::~:~::-
|
||||
LAST-MODIFIED:20240821T160941Z
|
||||
SEQUENCE:0
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:LLVM Loop Optimization Discussion
|
||||
TRANSP:OPAQUE
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;TZID=America/New_York:20240904T110000
|
||||
DTEND;TZID=America/New_York:20240904T120000
|
||||
DTSTAMP:20240821T160951Z
|
||||
UID:58h3f0kd3aooohmeii0johh23c@google.com
|
||||
X-GOOGLE-CONFERENCE:https://meet.google.com/fmz-gspu-odg
|
||||
RECURRENCE-ID;TZID=America/New_York:20240904T110000
|
||||
CREATED:20240821T151507Z
|
||||
DESCRIPTION:LLVM Loop Optimization Discussion<br>Video call link: <a href="
|
||||
https://meet.google.com/fmz-gspu-odg" target="_blank">https://meet.google.c
|
||||
om/fmz-gspu-odg</a><br>Agenda/Minutes/Discussion: <a href="https://docs.goo
|
||||
gle.com/document/d/1sdzoyB11s0ccTZ3fobqctDpgJmRoFcz0sviKxqczs4g/edit?usp=sh
|
||||
aring" class="pastedDriveLink-0">https://docs.google.com/document/d/1sdzoyB
|
||||
11s0ccTZ3fobqctDpgJmRoFcz0sviKxqczs4g/edit?usp=sharing</a>\n\n-::~:~::~:~:~
|
||||
:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~::~:~::-\
|
||||
nJoin with Google Meet: https://meet.google.com/fmz-gspu-odg\nOr dial: (DE)
|
||||
+49 40 8081617343 PIN: 948106286#\nMore phone numbers: https://tel.meet/fm
|
||||
z-gspu-odg?pin=6273693382184&hs=7\n\nLearn more about Meet at: https://supp
|
||||
ort.google.com/a/users/answer/9282720\n\nPlease do not edit this section.\n
|
||||
-::~:~::~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~
|
||||
:~:~::~:~::-
|
||||
LAST-MODIFIED:20240821T160941Z
|
||||
SEQUENCE:0
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:LLVM Loop Optimization Discussion
|
||||
TRANSP:OPAQUE
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
BEGIN:VCALENDAR
|
||||
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
||||
VERSION:2.0
|
||||
CALSCALE:GREGORIAN
|
||||
METHOD:PUBLISH
|
||||
X-WR-CALNAME:LLVM Loop Optimization Discussion
|
||||
X-WR-TIMEZONE:Europe/Berlin
|
||||
BEGIN:VTIMEZONE
|
||||
TZID:America/New_York
|
||||
X-LIC-LOCATION:America/New_York
|
||||
BEGIN:DAYLIGHT
|
||||
TZOFFSETFROM:-0500
|
||||
TZOFFSETTO:-0400
|
||||
TZNAME:EDT
|
||||
DTSTART:19700308T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
|
||||
END:DAYLIGHT
|
||||
BEGIN:STANDARD
|
||||
TZOFFSETFROM:-0400
|
||||
TZOFFSETTO:-0500
|
||||
TZNAME:EST
|
||||
DTSTART:19701101T020000
|
||||
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
|
||||
END:STANDARD
|
||||
END:VTIMEZONE
|
||||
BEGIN:VEVENT
|
||||
DTSTART;TZID=America/New_York:20240904T110000
|
||||
DTEND;TZID=America/New_York:20240904T120000
|
||||
RRULE:FREQ=MONTHLY;BYDAY=1WE
|
||||
DTSTAMP:20240821T160951Z
|
||||
UID:58h3f0kd3aooohmeii0johh23c@google.com
|
||||
X-GOOGLE-CONFERENCE:https://meet.google.com/fmz-gspu-odg
|
||||
CREATED:20240821T151507Z
|
||||
DESCRIPTION:LLVM Loop Optimization Discussion<br>Video call link: <a href="
|
||||
https://meet.google.com/fmz-gspu-odg" target="_blank">https://meet.google.c
|
||||
om/fmz-gspu-odg</a><br>Agenda/Minutes/Discussion: <a href="https://docs.goo
|
||||
gle.com/document/d/1sdzoyB11s0ccTZ3fobqctDpgJmRoFcz0sviKxqczs4g/edit?usp=sh
|
||||
aring" class="pastedDriveLink-0">https://docs.google.com/document/d/1sdzoyB
|
||||
11s0ccTZ3fobqctDpgJmRoFcz0sviKxqczs4g/edit?usp=sharing</a>\n\n-::~:~::~:~:~
|
||||
:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~::~:~::-\
|
||||
nJoin with Google Meet: https://meet.google.com/fmz-gspu-odg\nOr dial: (DE)
|
||||
+49 40 8081617343 PIN: 948106286#\nMore phone numbers: https://tel.meet/fm
|
||||
z-gspu-odg?pin=6273693382184&hs=7\n\nLearn more about Meet at: https://supp
|
||||
ort.google.com/a/users/answer/9282720\n\nPlease do not edit this section.\n
|
||||
-::~:~::~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~
|
||||
:~:~::~:~::-
|
||||
LAST-MODIFIED:20240821T160941Z
|
||||
SEQUENCE:0
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:LLVM Loop Optimization Discussion
|
||||
TRANSP:OPAQUE
|
||||
END:VEVENT
|
||||
BEGIN:VEVENT
|
||||
DTSTART;TZID=America/New_York:20240904T110000
|
||||
DTEND;TZID=America/New_York:20240904T120000
|
||||
DTSTAMP:20240821T160951Z
|
||||
UID:58h3f0kd3aooohmeii0johh23c@google.com
|
||||
X-GOOGLE-CONFERENCE:https://meet.google.com/fmz-gspu-odg
|
||||
RECURRENCE-ID;TZID=America/New_York:20240904T110000
|
||||
CREATED:20240821T151507Z
|
||||
DESCRIPTION:LLVM Loop Optimization Discussion<br>Video call link: <a href="
|
||||
https://meet.google.com/fmz-gspu-odg" target="_blank">https://meet.google.c
|
||||
om/fmz-gspu-odg</a><br>Agenda/Minutes/Discussion: <a href="https://docs.goo
|
||||
gle.com/document/d/1sdzoyB11s0ccTZ3fobqctDpgJmRoFcz0sviKxqczs4g/edit?usp=sh
|
||||
aring" class="pastedDriveLink-0">https://docs.google.com/document/d/1sdzoyB
|
||||
11s0ccTZ3fobqctDpgJmRoFcz0sviKxqczs4g/edit?usp=sharing</a>\n\n-::~:~::~:~:~
|
||||
:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~::~:~::-\
|
||||
nJoin with Google Meet: https://meet.google.com/fmz-gspu-odg\nOr dial: (DE)
|
||||
+49 40 8081617343 PIN: 948106286#\nMore phone numbers: https://tel.meet/fm
|
||||
z-gspu-odg?pin=6273693382184&hs=7\n\nLearn more about Meet at: https://supp
|
||||
ort.google.com/a/users/answer/9282720\n\nPlease do not edit this section.\n
|
||||
-::~:~::~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~:~
|
||||
:~:~::~:~::-
|
||||
LAST-MODIFIED:20240821T160941Z
|
||||
SEQUENCE:0
|
||||
STATUS:CONFIRMED
|
||||
SUMMARY:LLVM Loop Optimization Discussion
|
||||
TRANSP:OPAQUE
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
|
@ -1,19 +1,19 @@
|
||||
# Thread caches
|
||||
rpmalloc has a thread cache of free memory blocks which can be used in allocations without interfering with other threads or going to system to map more memory, as well as a global cache shared by all threads to let spans of memory pages flow between threads. Configuring the size of these caches can be crucial to obtaining good performance while minimizing memory overhead blowup. Below is a simple case study using the benchmark tool to compare different thread cache configurations for rpmalloc.
|
||||
|
||||
The rpmalloc thread cache is configured to be unlimited, performance oriented as meaning default values, size oriented where both thread cache and global cache is reduced significantly, or disabled where both thread and global caches are disabled and completely free pages are directly unmapped.
|
||||
|
||||
The benchmark is configured to run threads allocating 150000 blocks distributed in the `[16, 16000]` bytes range with a linear falloff probability. It runs 1000 loops, and every iteration 75000 blocks (50%) are freed and allocated in a scattered pattern. There are no cross thread allocations/deallocations. Parameters: `benchmark n 0 0 0 1000 150000 75000 16 16000`. The benchmarks are run on an Ubuntu 16.10 machine with 8 cores (4 physical, HT) and 12GiB RAM.
|
||||
|
||||
The benchmark also includes results for the standard library malloc implementation as a reference for comparison with the nocache setting.
|
||||
|
||||
![Ubuntu 16.10 random [16, 16000] bytes, 8 cores](https://docs.google.com/spreadsheets/d/1NWNuar1z0uPCB5iVS_Cs6hSo2xPkTmZf0KsgWS_Fb_4/pubchart?oid=387883204&format=image)
|
||||
![Ubuntu 16.10 random [16, 16000] bytes, 8 cores](https://docs.google.com/spreadsheets/d/1NWNuar1z0uPCB5iVS_Cs6hSo2xPkTmZf0KsgWS_Fb_4/pubchart?oid=1644710241&format=image)
|
||||
|
||||
For single threaded case the unlimited cache and performance oriented cache settings have identical performance and memory overhead, indicating that the memory pages fit in the combined thread and global cache. As number of threads increase to 2-4 threads, the performance settings have slightly higher performance which can seem odd at first, but can be explained by low contention on the global cache where some memory pages can flow between threads without stalling, reducing the overall number of calls to map new memory pages (also indicated by the slightly lower memory overhead).
|
||||
|
||||
As threads increase even more to 5-10 threads, the increased contention and eventual limit of global cache cause the unlimited setting to gain a slight advantage in performance. As expected the memory overhead remains constant for unlimited caches, while going down for performance setting when number of threads increases.
|
||||
|
||||
The size oriented setting maintain good performance compared to the standard library while reducing the memory overhead compared to the performance setting with a decent amount.
|
||||
|
||||
The nocache setting still outperforms the reference standard library allocator for workloads up to 6 threads while maintaining a near zero memory overhead, which is even slightly lower than the standard library. For use case scenarios where number of allocation of each size class is lower the overhead in rpmalloc from the 64KiB span size will of course increase.
|
||||
# Thread caches
|
||||
rpmalloc has a thread cache of free memory blocks which can be used in allocations without interfering with other threads or going to system to map more memory, as well as a global cache shared by all threads to let spans of memory pages flow between threads. Configuring the size of these caches can be crucial to obtaining good performance while minimizing memory overhead blowup. Below is a simple case study using the benchmark tool to compare different thread cache configurations for rpmalloc.
|
||||
|
||||
The rpmalloc thread cache is configured to be unlimited, performance oriented as meaning default values, size oriented where both thread cache and global cache is reduced significantly, or disabled where both thread and global caches are disabled and completely free pages are directly unmapped.
|
||||
|
||||
The benchmark is configured to run threads allocating 150000 blocks distributed in the `[16, 16000]` bytes range with a linear falloff probability. It runs 1000 loops, and every iteration 75000 blocks (50%) are freed and allocated in a scattered pattern. There are no cross thread allocations/deallocations. Parameters: `benchmark n 0 0 0 1000 150000 75000 16 16000`. The benchmarks are run on an Ubuntu 16.10 machine with 8 cores (4 physical, HT) and 12GiB RAM.
|
||||
|
||||
The benchmark also includes results for the standard library malloc implementation as a reference for comparison with the nocache setting.
|
||||
|
||||
![Ubuntu 16.10 random [16, 16000] bytes, 8 cores](https://docs.google.com/spreadsheets/d/1NWNuar1z0uPCB5iVS_Cs6hSo2xPkTmZf0KsgWS_Fb_4/pubchart?oid=387883204&format=image)
|
||||
![Ubuntu 16.10 random [16, 16000] bytes, 8 cores](https://docs.google.com/spreadsheets/d/1NWNuar1z0uPCB5iVS_Cs6hSo2xPkTmZf0KsgWS_Fb_4/pubchart?oid=1644710241&format=image)
|
||||
|
||||
For single threaded case the unlimited cache and performance oriented cache settings have identical performance and memory overhead, indicating that the memory pages fit in the combined thread and global cache. As number of threads increase to 2-4 threads, the performance settings have slightly higher performance which can seem odd at first, but can be explained by low contention on the global cache where some memory pages can flow between threads without stalling, reducing the overall number of calls to map new memory pages (also indicated by the slightly lower memory overhead).
|
||||
|
||||
As threads increase even more to 5-10 threads, the increased contention and eventual limit of global cache cause the unlimited setting to gain a slight advantage in performance. As expected the memory overhead remains constant for unlimited caches, while going down for performance setting when number of threads increases.
|
||||
|
||||
The size oriented setting maintain good performance compared to the standard library while reducing the memory overhead compared to the performance setting with a decent amount.
|
||||
|
||||
The nocache setting still outperforms the reference standard library allocator for workloads up to 6 threads while maintaining a near zero memory overhead, which is even slightly lower than the standard library. For use case scenarios where number of allocation of each size class is lower the overhead in rpmalloc from the 64KiB span size will of course increase.
|
||||
|
@ -1,220 +1,220 @@
|
||||
# rpmalloc - General Purpose Memory Allocator
|
||||
This library provides a cross platform lock free thread caching 16-byte aligned memory allocator implemented in C.
|
||||
This is a fork of rpmalloc 1.4.5.
|
||||
|
||||
Platforms currently supported:
|
||||
|
||||
- Windows
|
||||
- MacOS
|
||||
- iOS
|
||||
- Linux
|
||||
- Android
|
||||
- Haiku
|
||||
|
||||
The code should be easily portable to any platform with atomic operations and an mmap-style virtual memory management API. The API used to map/unmap memory pages can be configured in runtime to a custom implementation and mapping granularity/size.
|
||||
|
||||
This library is put in the public domain; you can redistribute it and/or modify it without any restrictions. Or, if you choose, you can use it under the MIT license.
|
||||
|
||||
# Performance
|
||||
We believe rpmalloc is faster than most popular memory allocators like tcmalloc, hoard, ptmalloc3 and others without causing extra allocated memory overhead in the thread caches compared to these allocators. We also believe the implementation to be easier to read and modify compared to these allocators, as it is a single source file of ~3000 lines of C code. All allocations have a natural 16-byte alignment.
|
||||
|
||||
Contained in a parallel repository is a benchmark utility that performs interleaved unaligned allocations and deallocations (both in-thread and cross-thread) in multiple threads. It measures number of memory operations performed per CPU second, as well as memory overhead by comparing the virtual memory mapped with the number of bytes requested in allocation calls. The setup of number of thread, cross-thread deallocation rate and allocation size limits is configured by command line arguments.
|
||||
|
||||
https://github.com/mjansson/rpmalloc-benchmark
|
||||
|
||||
Below is an example performance comparison chart of rpmalloc and other popular allocator implementations, with default configurations used.
|
||||
|
||||
![Ubuntu 16.10, random [16, 8000] bytes, 8 cores](https://docs.google.com/spreadsheets/d/1NWNuar1z0uPCB5iVS_Cs6hSo2xPkTmZf0KsgWS_Fb_4/pubchart?oid=301017877&format=image)
|
||||
|
||||
The benchmark producing these numbers were run on an Ubuntu 16.10 machine with 8 logical cores (4 physical, HT). The actual numbers are not to be interpreted as absolute performance figures, but rather as relative comparisons between the different allocators. For additional benchmark results, see the [BENCHMARKS](BENCHMARKS.md) file.
|
||||
|
||||
Configuration of the thread and global caches can be important depending on your use pattern. See [CACHE](CACHE.md) for a case study and some comments/guidelines.
|
||||
|
||||
# Required functions
|
||||
|
||||
Before calling any other function in the API, you __MUST__ call the initialization function, either __rpmalloc_initialize__ or __rpmalloc_initialize_config__, or you will get undefined behaviour when calling other rpmalloc entry point.
|
||||
|
||||
Before terminating your use of the allocator, you __SHOULD__ call __rpmalloc_finalize__ in order to release caches and unmap virtual memory, as well as prepare the allocator for global scope cleanup at process exit or dynamic library unload depending on your use case.
|
||||
|
||||
# Using
|
||||
The easiest way to use the library is simply adding __rpmalloc.[h|c]__ to your project and compile them along with your sources. This contains only the rpmalloc specific entry points and does not provide internal hooks to process and/or thread creation at the moment. You are required to call these functions from your own code in order to initialize and finalize the allocator in your process and threads:
|
||||
|
||||
__rpmalloc_initialize__ : Call at process start to initialize the allocator
|
||||
|
||||
__rpmalloc_initialize_config__ : Optional entry point to call at process start to initialize the allocator with a custom memory mapping backend, memory page size and mapping granularity.
|
||||
|
||||
__rpmalloc_finalize__: Call at process exit to finalize the allocator
|
||||
|
||||
__rpmalloc_thread_initialize__: Call at each thread start to initialize the thread local data for the allocator
|
||||
|
||||
__rpmalloc_thread_finalize__: Call at each thread exit to finalize and release thread cache back to global cache
|
||||
|
||||
__rpmalloc_config__: Get the current runtime configuration of the allocator
|
||||
|
||||
Then simply use the __rpmalloc__/__rpfree__ and the other malloc style replacement functions. Remember all allocations are 16-byte aligned, so no need to call the explicit rpmemalign/rpaligned_alloc/rpposix_memalign functions unless you need greater alignment, they are simply wrappers to make it easier to replace in existing code.
|
||||
|
||||
If you wish to override the standard library malloc family of functions and have automatic initialization/finalization of process and threads, define __ENABLE_OVERRIDE__ to non-zero which will include the `malloc.c` file in compilation of __rpmalloc.c__, and then rebuild the library or your project where you added the rpmalloc source. If you compile rpmalloc as a separate library you must make the linker use the override symbols from the library by referencing at least one symbol. The easiest way is to simply include `rpmalloc.h` in at least one source file and call `rpmalloc_linker_reference` somewhere - it's a dummy empty function. On Windows platforms and C++ overrides you have to `#include <rpnew.h>` in at least one source file and also manually handle the initialize/finalize of the process and all threads. The list of libc entry points replaced may not be complete, use libc/stdc++ replacement only as a convenience for testing the library on an existing code base, not a final solution.
|
||||
|
||||
For explicit first class heaps, see the __rpmalloc_heap_*__ API under [first class heaps](#first-class-heaps) section, requiring __RPMALLOC_FIRST_CLASS_HEAPS__ tp be defined to 1.
|
||||
|
||||
# Building
|
||||
To compile as a static library run the configure python script which generates a Ninja build script, then build using ninja. The ninja build produces two static libraries, one named `rpmalloc` and one named `rpmallocwrap`, where the latter includes the libc entry point overrides.
|
||||
|
||||
The configure + ninja build also produces two shared object/dynamic libraries. The `rpmallocwrap` shared library can be used with LD_PRELOAD/DYLD_INSERT_LIBRARIES to inject in a preexisting binary, replacing any malloc/free family of function calls. This is only implemented for Linux and macOS targets. The list of libc entry points replaced may not be complete, use preloading as a convenience for testing the library on an existing binary, not a final solution. The dynamic library also provides automatic init/fini of process and threads for all platforms.
|
||||
|
||||
The latest stable release is available in the master branch. For latest development code, use the develop branch.
|
||||
|
||||
# Cache configuration options
|
||||
Free memory pages are cached both per thread and in a global cache for all threads. The size of the thread caches is determined by an adaptive scheme where each cache is limited by a percentage of the maximum allocation count of the corresponding size class. The size of the global caches is determined by a multiple of the maximum of all thread caches. The factors controlling the cache sizes can be set by editing the individual defines in the `rpmalloc.c` source file for fine tuned control.
|
||||
|
||||
__ENABLE_UNLIMITED_CACHE__: By default defined to 0, set to 1 to make all caches infinite, i.e never release spans to global cache unless thread finishes and never unmap memory pages back to the OS. Highest performance but largest memory overhead.
|
||||
|
||||
__ENABLE_UNLIMITED_GLOBAL_CACHE__: By default defined to 0, set to 1 to make global caches infinite, i.e never unmap memory pages back to the OS.
|
||||
|
||||
__ENABLE_UNLIMITED_THREAD_CACHE__: By default defined to 0, set to 1 to make thread caches infinite, i.e never release spans to global cache unless thread finishes.
|
||||
|
||||
__ENABLE_GLOBAL_CACHE__: By default defined to 1, enables the global cache shared between all threads. Set to 0 to disable the global cache and directly unmap pages evicted from the thread cache.
|
||||
|
||||
__ENABLE_THREAD_CACHE__: By default defined to 1, enables the per-thread cache. Set to 0 to disable the thread cache and directly unmap pages no longer in use (also disables the global cache).
|
||||
|
||||
__ENABLE_ADAPTIVE_THREAD_CACHE__: Introduces a simple heuristics in the thread cache size, keeping 25% of the high water mark for each span count class.
|
||||
|
||||
# Other configuration options
|
||||
Detailed statistics are available if __ENABLE_STATISTICS__ is defined to 1 (default is 0, or disabled), either on compile command line or by setting the value in `rpmalloc.c`. This will cause a slight overhead in runtime to collect statistics for each memory operation, and will also add 4 bytes overhead per allocation to track sizes.
|
||||
|
||||
Integer safety checks on all calls are enabled if __ENABLE_VALIDATE_ARGS__ is defined to 1 (default is 0, or disabled), either on compile command line or by setting the value in `rpmalloc.c`. If enabled, size arguments to the global entry points are verified not to cause integer overflows in calculations.
|
||||
|
||||
Asserts are enabled if __ENABLE_ASSERTS__ is defined to 1 (default is 0, or disabled), either on compile command line or by setting the value in `rpmalloc.c`.
|
||||
|
||||
To include __malloc.c__ in compilation and provide overrides of standard library malloc entry points define __ENABLE_OVERRIDE__ to 1. To enable automatic initialization of finalization of process and threads in order to preload the library into executables using standard library malloc, define __ENABLE_PRELOAD__ to 1.
|
||||
|
||||
To enable the runtime configurable memory page and span sizes, define __RPMALLOC_CONFIGURABLE__ to 1. By default, memory page size is determined by system APIs and memory span size is set to 64KiB.
|
||||
|
||||
To enable support for first class heaps, define __RPMALLOC_FIRST_CLASS_HEAPS__ to 1. By default, the first class heap API is disabled.
|
||||
|
||||
# Huge pages
|
||||
The allocator has support for huge/large pages on Windows, Linux and MacOS. To enable it, pass a non-zero value in the config value `enable_huge_pages` when initializing the allocator with `rpmalloc_initialize_config`. If the system does not support huge pages it will be automatically disabled. You can query the status by looking at `enable_huge_pages` in the config returned from a call to `rpmalloc_config` after initialization is done.
|
||||
|
||||
# Quick overview
|
||||
The allocator is similar in spirit to tcmalloc from the [Google Performance Toolkit](https://github.com/gperftools/gperftools). It uses separate heaps for each thread and partitions memory blocks according to a preconfigured set of size classes, up to 2MiB. Larger blocks are mapped and unmapped directly. Allocations for different size classes will be served from different set of memory pages, each "span" of pages is dedicated to one size class. Spans of pages can flow between threads when the thread cache overflows and are released to a global cache, or when the thread ends. Unlike tcmalloc, single blocks do not flow between threads, only entire spans of pages.
|
||||
|
||||
# Implementation details
|
||||
The allocator is based on a fixed but configurable page alignment (defaults to 64KiB) and 16 byte block alignment, where all runs of memory pages (spans) are mapped to this alignment boundary. On Windows this is automatically guaranteed up to 64KiB by the VirtualAlloc granularity, and on mmap systems it is achieved by oversizing the mapping and aligning the returned virtual memory address to the required boundaries. By aligning to a fixed size the free operation can locate the header of the memory span without having to do a table lookup (as tcmalloc does) by simply masking out the low bits of the address (for 64KiB this would be the low 16 bits).
|
||||
|
||||
Memory blocks are divided into three categories. For 64KiB span size/alignment the small blocks are [16, 1024] bytes, medium blocks (1024, 32256] bytes, and large blocks (32256, 2097120] bytes. The three categories are further divided in size classes. If the span size is changed, the small block classes remain but medium blocks go from (1024, span size] bytes.
|
||||
|
||||
Small blocks have a size class granularity of 16 bytes each in 64 buckets. Medium blocks have a granularity of 512 bytes, 61 buckets (default). Large blocks have the same granularity as the configured span size (default 64KiB). All allocations are fitted to these size class boundaries (an allocation of 36 bytes will allocate a block of 48 bytes). Each small and medium size class has an associated span (meaning a contiguous set of memory pages) configuration describing how many pages the size class will allocate each time the cache is empty and a new allocation is requested.
|
||||
|
||||
Spans for small and medium blocks are cached in four levels to avoid calls to map/unmap memory pages. The first level is a per thread single active span for each size class. The second level is a per thread list of partially free spans for each size class. The third level is a per thread list of free spans. The fourth level is a global list of free spans.
|
||||
|
||||
Each span for a small and medium size class keeps track of how many blocks are allocated/free, as well as a list of which blocks that are free for allocation. To avoid locks, each span is completely owned by the allocating thread, and all cross-thread deallocations will be deferred to the owner thread through a separate free list per span.
|
||||
|
||||
Large blocks, or super spans, are cached in two levels. The first level is a per thread list of free super spans. The second level is a global list of free super spans.
|
||||
|
||||
# Memory mapping
|
||||
By default the allocator uses OS APIs to map virtual memory pages as needed, either `VirtualAlloc` on Windows or `mmap` on POSIX systems. If you want to use your own custom memory mapping provider you can use __rpmalloc_initialize_config__ and pass function pointers to map and unmap virtual memory. These function should reserve and free the requested number of bytes.
|
||||
|
||||
The returned memory address from the memory map function MUST be aligned to the memory page size and the memory span size (which ever is larger), both of which is configurable. Either provide the page and span sizes during initialization using __rpmalloc_initialize_config__, or use __rpmalloc_config__ to find the required alignment which is equal to the maximum of page and span size. The span size MUST be a power of two in [4096, 262144] range, and be a multiple or divisor of the memory page size.
|
||||
|
||||
Memory mapping requests are always done in multiples of the memory page size. You can specify a custom page size when initializing rpmalloc with __rpmalloc_initialize_config__, or pass 0 to let rpmalloc determine the system memory page size using OS APIs. The page size MUST be a power of two.
|
||||
|
||||
To reduce system call overhead, memory spans are mapped in batches controlled by the `span_map_count` configuration variable (which defaults to the `DEFAULT_SPAN_MAP_COUNT` value if 0, which in turn is sized according to the cache configuration define, defaulting to 64). If the memory page size is larger than the span size, the number of spans to map in a single call will be adjusted to guarantee a multiple of the page size, and the spans will be kept mapped until the entire span range can be unmapped in one call (to avoid trying to unmap partial pages).
|
||||
|
||||
On macOS and iOS mmap requests are tagged with tag 240 for easy identification with the vmmap tool.
|
||||
|
||||
# Span breaking
|
||||
Super spans (spans a multiple > 1 of the span size) can be subdivided into smaller spans to fulfill a need to map a new span of memory. By default the allocator will greedily grab and break any larger span from the available caches before mapping new virtual memory. However, spans can currently not be glued together to form larger super spans again. Subspans can traverse the cache and be used by different threads individually.
|
||||
|
||||
A span that is a subspan of a larger super span can be individually decommitted to reduce physical memory pressure when the span is evicted from caches and scheduled to be unmapped. The entire original super span will keep track of the subspans it is broken up into, and when the entire range is decommitted the super span will be unmapped. This allows platforms like Windows that require the entire virtual memory range that was mapped in a call to VirtualAlloc to be unmapped in one call to VirtualFree, while still decommitting individual pages in subspans (if the page size is smaller than the span size).
|
||||
|
||||
If you use a custom memory map/unmap function you need to take this into account by looking at the `release` parameter given to the `memory_unmap` function. It is set to 0 for decommitting individual pages and the total super span byte size for finally releasing the entire super span memory range.
|
||||
|
||||
# Memory fragmentation
|
||||
There is no memory fragmentation by the allocator in the sense that it will not leave unallocated and unusable "holes" in the memory pages by calls to allocate and free blocks of different sizes. This is due to the fact that the memory pages allocated for each size class is split up in perfectly aligned blocks which are not reused for a request of a different size. The block freed by a call to `rpfree` will always be immediately available for an allocation request within the same size class.
|
||||
|
||||
However, there is memory fragmentation in the meaning that a request for x bytes followed by a request of y bytes where x and y are at least one size class different in size will return blocks that are at least one memory page apart in virtual address space. Only blocks of the same size will potentially be within the same memory page span.
|
||||
|
||||
rpmalloc keeps an "active span" and free list for each size class. This leads to back-to-back allocations will most likely be served from within the same span of memory pages (unless the span runs out of free blocks). The rpmalloc implementation will also use any "holes" in memory pages in semi-filled spans before using a completely free span.
|
||||
|
||||
# First class heaps
|
||||
rpmalloc provides a first class heap type with explicit heap control API. Heaps are maintained with calls to __rpmalloc_heap_acquire__ and __rpmalloc_heap_release__ and allocations/frees are done with __rpmalloc_heap_alloc__ and __rpmalloc_heap_free__. See the `rpmalloc.h` documentation for the full list of functions in the heap API. The main use case of explicit heap control is to scope allocations in a heap and release everything with a single call to __rpmalloc_heap_free_all__ without having to maintain ownership of memory blocks. Note that the heap API is not thread-safe, the caller must make sure that each heap is only used in a single thread at any given time.
|
||||
|
||||
# Producer-consumer scenario
|
||||
Compared to the some other allocators, rpmalloc does not suffer as much from a producer-consumer thread scenario where one thread allocates memory blocks and another thread frees the blocks. In some allocators the free blocks need to traverse both the thread cache of the thread doing the free operations as well as the global cache before being reused in the allocating thread. In rpmalloc the freed blocks will be reused as soon as the allocating thread needs to get new spans from the thread cache. This enables faster release of completely freed memory pages as blocks in a memory page will not be aliased between different owning threads.
|
||||
|
||||
# Best case scenarios
|
||||
Threads that keep ownership of allocated memory blocks within the thread and free the blocks from the same thread will have optimal performance.
|
||||
|
||||
Threads that have allocation patterns where the difference in memory usage high and low water marks fit within the thread cache thresholds in the allocator will never touch the global cache except during thread init/fini and have optimal performance. Tweaking the cache limits can be done on a per-size-class basis.
|
||||
|
||||
# Worst case scenarios
|
||||
Since each thread cache maps spans of memory pages per size class, a thread that allocates just a few blocks of each size class (16, 32, ...) for many size classes will never fill each bucket, and thus map a lot of memory pages while only using a small fraction of the mapped memory. However, the wasted memory will always be less than 4KiB (or the configured memory page size) per size class as each span is initialized one memory page at a time. The cache for free spans will be reused by all size classes.
|
||||
|
||||
Threads that perform a lot of allocations and deallocations in a pattern that have a large difference in high and low water marks, and that difference is larger than the thread cache size, will put a lot of contention on the global cache. What will happen is the thread cache will overflow on each low water mark causing pages to be released to the global cache, then underflow on high water mark causing pages to be re-acquired from the global cache. This can be mitigated by changing the __MAX_SPAN_CACHE_DIVISOR__ define in the source code (at the cost of higher average memory overhead).
|
||||
|
||||
# Caveats
|
||||
VirtualAlloc has an internal granularity of 64KiB. However, mmap lacks this granularity control, and the implementation instead oversizes the memory mapping with configured span size to be able to always return a memory area with the required alignment. Since the extra memory pages are never touched this will not result in extra committed physical memory pages, but rather only increase virtual memory address space.
|
||||
|
||||
All entry points assume the passed values are valid, for example passing an invalid pointer to free would most likely result in a segmentation fault. __The library does not try to guard against errors!__.
|
||||
|
||||
To support global scope data doing dynamic allocation/deallocation such as C++ objects with custom constructors and destructors, the call to __rpmalloc_finalize__ will not completely terminate the allocator but rather empty all caches and put the allocator in finalization mode. Once this call has been made, the allocator is no longer thread safe and expects all remaining calls to originate from global data destruction on main thread. Any spans or heaps becoming free during this phase will be immediately unmapped to allow correct teardown of the process or dynamic library without any leaks.
|
||||
|
||||
# Other languages
|
||||
|
||||
[Johan Andersson](https://github.com/repi) at Embark has created a Rust wrapper available at [rpmalloc-rs](https://github.com/EmbarkStudios/rpmalloc-rs)
|
||||
|
||||
[Stas Denisov](https://github.com/nxrighthere) has created a C# wrapper available at [Rpmalloc-CSharp](https://github.com/nxrighthere/Rpmalloc-CSharp)
|
||||
|
||||
# License
|
||||
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org>
|
||||
|
||||
|
||||
You can also use this software under the MIT license if public domain is
|
||||
not recognized in your country
|
||||
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Mattias Jansson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
# rpmalloc - General Purpose Memory Allocator
|
||||
This library provides a cross platform lock free thread caching 16-byte aligned memory allocator implemented in C.
|
||||
This is a fork of rpmalloc 1.4.5.
|
||||
|
||||
Platforms currently supported:
|
||||
|
||||
- Windows
|
||||
- MacOS
|
||||
- iOS
|
||||
- Linux
|
||||
- Android
|
||||
- Haiku
|
||||
|
||||
The code should be easily portable to any platform with atomic operations and an mmap-style virtual memory management API. The API used to map/unmap memory pages can be configured in runtime to a custom implementation and mapping granularity/size.
|
||||
|
||||
This library is put in the public domain; you can redistribute it and/or modify it without any restrictions. Or, if you choose, you can use it under the MIT license.
|
||||
|
||||
# Performance
|
||||
We believe rpmalloc is faster than most popular memory allocators like tcmalloc, hoard, ptmalloc3 and others without causing extra allocated memory overhead in the thread caches compared to these allocators. We also believe the implementation to be easier to read and modify compared to these allocators, as it is a single source file of ~3000 lines of C code. All allocations have a natural 16-byte alignment.
|
||||
|
||||
Contained in a parallel repository is a benchmark utility that performs interleaved unaligned allocations and deallocations (both in-thread and cross-thread) in multiple threads. It measures number of memory operations performed per CPU second, as well as memory overhead by comparing the virtual memory mapped with the number of bytes requested in allocation calls. The setup of number of thread, cross-thread deallocation rate and allocation size limits is configured by command line arguments.
|
||||
|
||||
https://github.com/mjansson/rpmalloc-benchmark
|
||||
|
||||
Below is an example performance comparison chart of rpmalloc and other popular allocator implementations, with default configurations used.
|
||||
|
||||
![Ubuntu 16.10, random [16, 8000] bytes, 8 cores](https://docs.google.com/spreadsheets/d/1NWNuar1z0uPCB5iVS_Cs6hSo2xPkTmZf0KsgWS_Fb_4/pubchart?oid=301017877&format=image)
|
||||
|
||||
The benchmark producing these numbers were run on an Ubuntu 16.10 machine with 8 logical cores (4 physical, HT). The actual numbers are not to be interpreted as absolute performance figures, but rather as relative comparisons between the different allocators. For additional benchmark results, see the [BENCHMARKS](BENCHMARKS.md) file.
|
||||
|
||||
Configuration of the thread and global caches can be important depending on your use pattern. See [CACHE](CACHE.md) for a case study and some comments/guidelines.
|
||||
|
||||
# Required functions
|
||||
|
||||
Before calling any other function in the API, you __MUST__ call the initialization function, either __rpmalloc_initialize__ or __rpmalloc_initialize_config__, or you will get undefined behaviour when calling other rpmalloc entry point.
|
||||
|
||||
Before terminating your use of the allocator, you __SHOULD__ call __rpmalloc_finalize__ in order to release caches and unmap virtual memory, as well as prepare the allocator for global scope cleanup at process exit or dynamic library unload depending on your use case.
|
||||
|
||||
# Using
|
||||
The easiest way to use the library is simply adding __rpmalloc.[h|c]__ to your project and compile them along with your sources. This contains only the rpmalloc specific entry points and does not provide internal hooks to process and/or thread creation at the moment. You are required to call these functions from your own code in order to initialize and finalize the allocator in your process and threads:
|
||||
|
||||
__rpmalloc_initialize__ : Call at process start to initialize the allocator
|
||||
|
||||
__rpmalloc_initialize_config__ : Optional entry point to call at process start to initialize the allocator with a custom memory mapping backend, memory page size and mapping granularity.
|
||||
|
||||
__rpmalloc_finalize__: Call at process exit to finalize the allocator
|
||||
|
||||
__rpmalloc_thread_initialize__: Call at each thread start to initialize the thread local data for the allocator
|
||||
|
||||
__rpmalloc_thread_finalize__: Call at each thread exit to finalize and release thread cache back to global cache
|
||||
|
||||
__rpmalloc_config__: Get the current runtime configuration of the allocator
|
||||
|
||||
Then simply use the __rpmalloc__/__rpfree__ and the other malloc style replacement functions. Remember all allocations are 16-byte aligned, so no need to call the explicit rpmemalign/rpaligned_alloc/rpposix_memalign functions unless you need greater alignment, they are simply wrappers to make it easier to replace in existing code.
|
||||
|
||||
If you wish to override the standard library malloc family of functions and have automatic initialization/finalization of process and threads, define __ENABLE_OVERRIDE__ to non-zero which will include the `malloc.c` file in compilation of __rpmalloc.c__, and then rebuild the library or your project where you added the rpmalloc source. If you compile rpmalloc as a separate library you must make the linker use the override symbols from the library by referencing at least one symbol. The easiest way is to simply include `rpmalloc.h` in at least one source file and call `rpmalloc_linker_reference` somewhere - it's a dummy empty function. On Windows platforms and C++ overrides you have to `#include <rpnew.h>` in at least one source file and also manually handle the initialize/finalize of the process and all threads. The list of libc entry points replaced may not be complete, use libc/stdc++ replacement only as a convenience for testing the library on an existing code base, not a final solution.
|
||||
|
||||
For explicit first class heaps, see the __rpmalloc_heap_*__ API under [first class heaps](#first-class-heaps) section, requiring __RPMALLOC_FIRST_CLASS_HEAPS__ tp be defined to 1.
|
||||
|
||||
# Building
|
||||
To compile as a static library run the configure python script which generates a Ninja build script, then build using ninja. The ninja build produces two static libraries, one named `rpmalloc` and one named `rpmallocwrap`, where the latter includes the libc entry point overrides.
|
||||
|
||||
The configure + ninja build also produces two shared object/dynamic libraries. The `rpmallocwrap` shared library can be used with LD_PRELOAD/DYLD_INSERT_LIBRARIES to inject in a preexisting binary, replacing any malloc/free family of function calls. This is only implemented for Linux and macOS targets. The list of libc entry points replaced may not be complete, use preloading as a convenience for testing the library on an existing binary, not a final solution. The dynamic library also provides automatic init/fini of process and threads for all platforms.
|
||||
|
||||
The latest stable release is available in the master branch. For latest development code, use the develop branch.
|
||||
|
||||
# Cache configuration options
|
||||
Free memory pages are cached both per thread and in a global cache for all threads. The size of the thread caches is determined by an adaptive scheme where each cache is limited by a percentage of the maximum allocation count of the corresponding size class. The size of the global caches is determined by a multiple of the maximum of all thread caches. The factors controlling the cache sizes can be set by editing the individual defines in the `rpmalloc.c` source file for fine tuned control.
|
||||
|
||||
__ENABLE_UNLIMITED_CACHE__: By default defined to 0, set to 1 to make all caches infinite, i.e never release spans to global cache unless thread finishes and never unmap memory pages back to the OS. Highest performance but largest memory overhead.
|
||||
|
||||
__ENABLE_UNLIMITED_GLOBAL_CACHE__: By default defined to 0, set to 1 to make global caches infinite, i.e never unmap memory pages back to the OS.
|
||||
|
||||
__ENABLE_UNLIMITED_THREAD_CACHE__: By default defined to 0, set to 1 to make thread caches infinite, i.e never release spans to global cache unless thread finishes.
|
||||
|
||||
__ENABLE_GLOBAL_CACHE__: By default defined to 1, enables the global cache shared between all threads. Set to 0 to disable the global cache and directly unmap pages evicted from the thread cache.
|
||||
|
||||
__ENABLE_THREAD_CACHE__: By default defined to 1, enables the per-thread cache. Set to 0 to disable the thread cache and directly unmap pages no longer in use (also disables the global cache).
|
||||
|
||||
__ENABLE_ADAPTIVE_THREAD_CACHE__: Introduces a simple heuristics in the thread cache size, keeping 25% of the high water mark for each span count class.
|
||||
|
||||
# Other configuration options
|
||||
Detailed statistics are available if __ENABLE_STATISTICS__ is defined to 1 (default is 0, or disabled), either on compile command line or by setting the value in `rpmalloc.c`. This will cause a slight overhead in runtime to collect statistics for each memory operation, and will also add 4 bytes overhead per allocation to track sizes.
|
||||
|
||||
Integer safety checks on all calls are enabled if __ENABLE_VALIDATE_ARGS__ is defined to 1 (default is 0, or disabled), either on compile command line or by setting the value in `rpmalloc.c`. If enabled, size arguments to the global entry points are verified not to cause integer overflows in calculations.
|
||||
|
||||
Asserts are enabled if __ENABLE_ASSERTS__ is defined to 1 (default is 0, or disabled), either on compile command line or by setting the value in `rpmalloc.c`.
|
||||
|
||||
To include __malloc.c__ in compilation and provide overrides of standard library malloc entry points define __ENABLE_OVERRIDE__ to 1. To enable automatic initialization of finalization of process and threads in order to preload the library into executables using standard library malloc, define __ENABLE_PRELOAD__ to 1.
|
||||
|
||||
To enable the runtime configurable memory page and span sizes, define __RPMALLOC_CONFIGURABLE__ to 1. By default, memory page size is determined by system APIs and memory span size is set to 64KiB.
|
||||
|
||||
To enable support for first class heaps, define __RPMALLOC_FIRST_CLASS_HEAPS__ to 1. By default, the first class heap API is disabled.
|
||||
|
||||
# Huge pages
|
||||
The allocator has support for huge/large pages on Windows, Linux and MacOS. To enable it, pass a non-zero value in the config value `enable_huge_pages` when initializing the allocator with `rpmalloc_initialize_config`. If the system does not support huge pages it will be automatically disabled. You can query the status by looking at `enable_huge_pages` in the config returned from a call to `rpmalloc_config` after initialization is done.
|
||||
|
||||
# Quick overview
|
||||
The allocator is similar in spirit to tcmalloc from the [Google Performance Toolkit](https://github.com/gperftools/gperftools). It uses separate heaps for each thread and partitions memory blocks according to a preconfigured set of size classes, up to 2MiB. Larger blocks are mapped and unmapped directly. Allocations for different size classes will be served from different set of memory pages, each "span" of pages is dedicated to one size class. Spans of pages can flow between threads when the thread cache overflows and are released to a global cache, or when the thread ends. Unlike tcmalloc, single blocks do not flow between threads, only entire spans of pages.
|
||||
|
||||
# Implementation details
|
||||
The allocator is based on a fixed but configurable page alignment (defaults to 64KiB) and 16 byte block alignment, where all runs of memory pages (spans) are mapped to this alignment boundary. On Windows this is automatically guaranteed up to 64KiB by the VirtualAlloc granularity, and on mmap systems it is achieved by oversizing the mapping and aligning the returned virtual memory address to the required boundaries. By aligning to a fixed size the free operation can locate the header of the memory span without having to do a table lookup (as tcmalloc does) by simply masking out the low bits of the address (for 64KiB this would be the low 16 bits).
|
||||
|
||||
Memory blocks are divided into three categories. For 64KiB span size/alignment the small blocks are [16, 1024] bytes, medium blocks (1024, 32256] bytes, and large blocks (32256, 2097120] bytes. The three categories are further divided in size classes. If the span size is changed, the small block classes remain but medium blocks go from (1024, span size] bytes.
|
||||
|
||||
Small blocks have a size class granularity of 16 bytes each in 64 buckets. Medium blocks have a granularity of 512 bytes, 61 buckets (default). Large blocks have the same granularity as the configured span size (default 64KiB). All allocations are fitted to these size class boundaries (an allocation of 36 bytes will allocate a block of 48 bytes). Each small and medium size class has an associated span (meaning a contiguous set of memory pages) configuration describing how many pages the size class will allocate each time the cache is empty and a new allocation is requested.
|
||||
|
||||
Spans for small and medium blocks are cached in four levels to avoid calls to map/unmap memory pages. The first level is a per thread single active span for each size class. The second level is a per thread list of partially free spans for each size class. The third level is a per thread list of free spans. The fourth level is a global list of free spans.
|
||||
|
||||
Each span for a small and medium size class keeps track of how many blocks are allocated/free, as well as a list of which blocks that are free for allocation. To avoid locks, each span is completely owned by the allocating thread, and all cross-thread deallocations will be deferred to the owner thread through a separate free list per span.
|
||||
|
||||
Large blocks, or super spans, are cached in two levels. The first level is a per thread list of free super spans. The second level is a global list of free super spans.
|
||||
|
||||
# Memory mapping
|
||||
By default the allocator uses OS APIs to map virtual memory pages as needed, either `VirtualAlloc` on Windows or `mmap` on POSIX systems. If you want to use your own custom memory mapping provider you can use __rpmalloc_initialize_config__ and pass function pointers to map and unmap virtual memory. These function should reserve and free the requested number of bytes.
|
||||
|
||||
The returned memory address from the memory map function MUST be aligned to the memory page size and the memory span size (which ever is larger), both of which is configurable. Either provide the page and span sizes during initialization using __rpmalloc_initialize_config__, or use __rpmalloc_config__ to find the required alignment which is equal to the maximum of page and span size. The span size MUST be a power of two in [4096, 262144] range, and be a multiple or divisor of the memory page size.
|
||||
|
||||
Memory mapping requests are always done in multiples of the memory page size. You can specify a custom page size when initializing rpmalloc with __rpmalloc_initialize_config__, or pass 0 to let rpmalloc determine the system memory page size using OS APIs. The page size MUST be a power of two.
|
||||
|
||||
To reduce system call overhead, memory spans are mapped in batches controlled by the `span_map_count` configuration variable (which defaults to the `DEFAULT_SPAN_MAP_COUNT` value if 0, which in turn is sized according to the cache configuration define, defaulting to 64). If the memory page size is larger than the span size, the number of spans to map in a single call will be adjusted to guarantee a multiple of the page size, and the spans will be kept mapped until the entire span range can be unmapped in one call (to avoid trying to unmap partial pages).
|
||||
|
||||
On macOS and iOS mmap requests are tagged with tag 240 for easy identification with the vmmap tool.
|
||||
|
||||
# Span breaking
|
||||
Super spans (spans a multiple > 1 of the span size) can be subdivided into smaller spans to fulfill a need to map a new span of memory. By default the allocator will greedily grab and break any larger span from the available caches before mapping new virtual memory. However, spans can currently not be glued together to form larger super spans again. Subspans can traverse the cache and be used by different threads individually.
|
||||
|
||||
A span that is a subspan of a larger super span can be individually decommitted to reduce physical memory pressure when the span is evicted from caches and scheduled to be unmapped. The entire original super span will keep track of the subspans it is broken up into, and when the entire range is decommitted the super span will be unmapped. This allows platforms like Windows that require the entire virtual memory range that was mapped in a call to VirtualAlloc to be unmapped in one call to VirtualFree, while still decommitting individual pages in subspans (if the page size is smaller than the span size).
|
||||
|
||||
If you use a custom memory map/unmap function you need to take this into account by looking at the `release` parameter given to the `memory_unmap` function. It is set to 0 for decommitting individual pages and the total super span byte size for finally releasing the entire super span memory range.
|
||||
|
||||
# Memory fragmentation
|
||||
There is no memory fragmentation by the allocator in the sense that it will not leave unallocated and unusable "holes" in the memory pages by calls to allocate and free blocks of different sizes. This is due to the fact that the memory pages allocated for each size class is split up in perfectly aligned blocks which are not reused for a request of a different size. The block freed by a call to `rpfree` will always be immediately available for an allocation request within the same size class.
|
||||
|
||||
However, there is memory fragmentation in the meaning that a request for x bytes followed by a request of y bytes where x and y are at least one size class different in size will return blocks that are at least one memory page apart in virtual address space. Only blocks of the same size will potentially be within the same memory page span.
|
||||
|
||||
rpmalloc keeps an "active span" and free list for each size class. This leads to back-to-back allocations will most likely be served from within the same span of memory pages (unless the span runs out of free blocks). The rpmalloc implementation will also use any "holes" in memory pages in semi-filled spans before using a completely free span.
|
||||
|
||||
# First class heaps
|
||||
rpmalloc provides a first class heap type with explicit heap control API. Heaps are maintained with calls to __rpmalloc_heap_acquire__ and __rpmalloc_heap_release__ and allocations/frees are done with __rpmalloc_heap_alloc__ and __rpmalloc_heap_free__. See the `rpmalloc.h` documentation for the full list of functions in the heap API. The main use case of explicit heap control is to scope allocations in a heap and release everything with a single call to __rpmalloc_heap_free_all__ without having to maintain ownership of memory blocks. Note that the heap API is not thread-safe, the caller must make sure that each heap is only used in a single thread at any given time.
|
||||
|
||||
# Producer-consumer scenario
|
||||
Compared to the some other allocators, rpmalloc does not suffer as much from a producer-consumer thread scenario where one thread allocates memory blocks and another thread frees the blocks. In some allocators the free blocks need to traverse both the thread cache of the thread doing the free operations as well as the global cache before being reused in the allocating thread. In rpmalloc the freed blocks will be reused as soon as the allocating thread needs to get new spans from the thread cache. This enables faster release of completely freed memory pages as blocks in a memory page will not be aliased between different owning threads.
|
||||
|
||||
# Best case scenarios
|
||||
Threads that keep ownership of allocated memory blocks within the thread and free the blocks from the same thread will have optimal performance.
|
||||
|
||||
Threads that have allocation patterns where the difference in memory usage high and low water marks fit within the thread cache thresholds in the allocator will never touch the global cache except during thread init/fini and have optimal performance. Tweaking the cache limits can be done on a per-size-class basis.
|
||||
|
||||
# Worst case scenarios
|
||||
Since each thread cache maps spans of memory pages per size class, a thread that allocates just a few blocks of each size class (16, 32, ...) for many size classes will never fill each bucket, and thus map a lot of memory pages while only using a small fraction of the mapped memory. However, the wasted memory will always be less than 4KiB (or the configured memory page size) per size class as each span is initialized one memory page at a time. The cache for free spans will be reused by all size classes.
|
||||
|
||||
Threads that perform a lot of allocations and deallocations in a pattern that have a large difference in high and low water marks, and that difference is larger than the thread cache size, will put a lot of contention on the global cache. What will happen is the thread cache will overflow on each low water mark causing pages to be released to the global cache, then underflow on high water mark causing pages to be re-acquired from the global cache. This can be mitigated by changing the __MAX_SPAN_CACHE_DIVISOR__ define in the source code (at the cost of higher average memory overhead).
|
||||
|
||||
# Caveats
|
||||
VirtualAlloc has an internal granularity of 64KiB. However, mmap lacks this granularity control, and the implementation instead oversizes the memory mapping with configured span size to be able to always return a memory area with the required alignment. Since the extra memory pages are never touched this will not result in extra committed physical memory pages, but rather only increase virtual memory address space.
|
||||
|
||||
All entry points assume the passed values are valid, for example passing an invalid pointer to free would most likely result in a segmentation fault. __The library does not try to guard against errors!__.
|
||||
|
||||
To support global scope data doing dynamic allocation/deallocation such as C++ objects with custom constructors and destructors, the call to __rpmalloc_finalize__ will not completely terminate the allocator but rather empty all caches and put the allocator in finalization mode. Once this call has been made, the allocator is no longer thread safe and expects all remaining calls to originate from global data destruction on main thread. Any spans or heaps becoming free during this phase will be immediately unmapped to allow correct teardown of the process or dynamic library without any leaks.
|
||||
|
||||
# Other languages
|
||||
|
||||
[Johan Andersson](https://github.com/repi) at Embark has created a Rust wrapper available at [rpmalloc-rs](https://github.com/EmbarkStudios/rpmalloc-rs)
|
||||
|
||||
[Stas Denisov](https://github.com/nxrighthere) has created a C# wrapper available at [Rpmalloc-CSharp](https://github.com/nxrighthere/Rpmalloc-CSharp)
|
||||
|
||||
# License
|
||||
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org>
|
||||
|
||||
|
||||
You can also use this software under the MIT license if public domain is
|
||||
not recognized in your country
|
||||
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Mattias Jansson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,428 +1,428 @@
|
||||
//===---------------------- rpmalloc.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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This library provides a cross-platform lock free thread caching malloc
|
||||
// implementation in C11.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#define RPMALLOC_EXPORT __attribute__((visibility("default")))
|
||||
#define RPMALLOC_ALLOCATOR
|
||||
#if (defined(__clang_major__) && (__clang_major__ < 4)) || \
|
||||
(defined(__GNUC__) && defined(ENABLE_PRELOAD) && ENABLE_PRELOAD)
|
||||
#define RPMALLOC_ATTRIB_MALLOC
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size)
|
||||
#else
|
||||
#define RPMALLOC_ATTRIB_MALLOC __attribute__((__malloc__))
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE(size) __attribute__((alloc_size(size)))
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size) \
|
||||
__attribute__((alloc_size(count, size)))
|
||||
#endif
|
||||
#define RPMALLOC_CDECL
|
||||
#elif defined(_MSC_VER)
|
||||
#define RPMALLOC_EXPORT
|
||||
#define RPMALLOC_ALLOCATOR __declspec(allocator) __declspec(restrict)
|
||||
#define RPMALLOC_ATTRIB_MALLOC
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size)
|
||||
#define RPMALLOC_CDECL __cdecl
|
||||
#else
|
||||
#define RPMALLOC_EXPORT
|
||||
#define RPMALLOC_ALLOCATOR
|
||||
#define RPMALLOC_ATTRIB_MALLOC
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size)
|
||||
#define RPMALLOC_CDECL
|
||||
#endif
|
||||
|
||||
//! Define RPMALLOC_CONFIGURABLE to enable configuring sizes. Will introduce
|
||||
// a very small overhead due to some size calculations not being compile time
|
||||
// constants
|
||||
#ifndef RPMALLOC_CONFIGURABLE
|
||||
#define RPMALLOC_CONFIGURABLE 0
|
||||
#endif
|
||||
|
||||
//! Define RPMALLOC_FIRST_CLASS_HEAPS to enable heap based API (rpmalloc_heap_*
|
||||
//! functions).
|
||||
// Will introduce a very small overhead to track fully allocated spans in heaps
|
||||
#ifndef RPMALLOC_FIRST_CLASS_HEAPS
|
||||
#define RPMALLOC_FIRST_CLASS_HEAPS 0
|
||||
#endif
|
||||
|
||||
//! Flag to rpaligned_realloc to not preserve content in reallocation
|
||||
#define RPMALLOC_NO_PRESERVE 1
|
||||
//! Flag to rpaligned_realloc to fail and return null pointer if grow cannot be
|
||||
//! done in-place,
|
||||
// in which case the original pointer is still valid (just like a call to
|
||||
// realloc which failes to allocate a new block).
|
||||
#define RPMALLOC_GROW_OR_FAIL 2
|
||||
|
||||
typedef struct rpmalloc_global_statistics_t {
|
||||
//! Current amount of virtual memory mapped, all of which might not have been
|
||||
//! committed (only if ENABLE_STATISTICS=1)
|
||||
size_t mapped;
|
||||
//! Peak amount of virtual memory mapped, all of which might not have been
|
||||
//! committed (only if ENABLE_STATISTICS=1)
|
||||
size_t mapped_peak;
|
||||
//! Current amount of memory in global caches for small and medium sizes
|
||||
//! (<32KiB)
|
||||
size_t cached;
|
||||
//! Current amount of memory allocated in huge allocations, i.e larger than
|
||||
//! LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1)
|
||||
size_t huge_alloc;
|
||||
//! Peak amount of memory allocated in huge allocations, i.e larger than
|
||||
//! LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1)
|
||||
size_t huge_alloc_peak;
|
||||
//! Total amount of memory mapped since initialization (only if
|
||||
//! ENABLE_STATISTICS=1)
|
||||
size_t mapped_total;
|
||||
//! Total amount of memory unmapped since initialization (only if
|
||||
//! ENABLE_STATISTICS=1)
|
||||
size_t unmapped_total;
|
||||
} rpmalloc_global_statistics_t;
|
||||
|
||||
typedef struct rpmalloc_thread_statistics_t {
|
||||
//! Current number of bytes available in thread size class caches for small
|
||||
//! and medium sizes (<32KiB)
|
||||
size_t sizecache;
|
||||
//! Current number of bytes available in thread span caches for small and
|
||||
//! medium sizes (<32KiB)
|
||||
size_t spancache;
|
||||
//! Total number of bytes transitioned from thread cache to global cache (only
|
||||
//! if ENABLE_STATISTICS=1)
|
||||
size_t thread_to_global;
|
||||
//! Total number of bytes transitioned from global cache to thread cache (only
|
||||
//! if ENABLE_STATISTICS=1)
|
||||
size_t global_to_thread;
|
||||
//! Per span count statistics (only if ENABLE_STATISTICS=1)
|
||||
struct {
|
||||
//! Currently used number of spans
|
||||
size_t current;
|
||||
//! High water mark of spans used
|
||||
size_t peak;
|
||||
//! Number of spans transitioned to global cache
|
||||
size_t to_global;
|
||||
//! Number of spans transitioned from global cache
|
||||
size_t from_global;
|
||||
//! Number of spans transitioned to thread cache
|
||||
size_t to_cache;
|
||||
//! Number of spans transitioned from thread cache
|
||||
size_t from_cache;
|
||||
//! Number of spans transitioned to reserved state
|
||||
size_t to_reserved;
|
||||
//! Number of spans transitioned from reserved state
|
||||
size_t from_reserved;
|
||||
//! Number of raw memory map calls (not hitting the reserve spans but
|
||||
//! resulting in actual OS mmap calls)
|
||||
size_t map_calls;
|
||||
} span_use[64];
|
||||
//! Per size class statistics (only if ENABLE_STATISTICS=1)
|
||||
struct {
|
||||
//! Current number of allocations
|
||||
size_t alloc_current;
|
||||
//! Peak number of allocations
|
||||
size_t alloc_peak;
|
||||
//! Total number of allocations
|
||||
size_t alloc_total;
|
||||
//! Total number of frees
|
||||
size_t free_total;
|
||||
//! Number of spans transitioned to cache
|
||||
size_t spans_to_cache;
|
||||
//! Number of spans transitioned from cache
|
||||
size_t spans_from_cache;
|
||||
//! Number of spans transitioned from reserved state
|
||||
size_t spans_from_reserved;
|
||||
//! Number of raw memory map calls (not hitting the reserve spans but
|
||||
//! resulting in actual OS mmap calls)
|
||||
size_t map_calls;
|
||||
} size_use[128];
|
||||
} rpmalloc_thread_statistics_t;
|
||||
|
||||
typedef struct rpmalloc_config_t {
|
||||
//! Map memory pages for the given number of bytes. The returned address MUST
|
||||
//! be
|
||||
// aligned to the rpmalloc span size, which will always be a power of two.
|
||||
// Optionally the function can store an alignment offset in the offset
|
||||
// variable in case it performs alignment and the returned pointer is offset
|
||||
// from the actual start of the memory region due to this alignment. The
|
||||
// alignment offset will be passed to the memory unmap function. The
|
||||
// alignment offset MUST NOT be larger than 65535 (storable in an uint16_t),
|
||||
// if it is you must use natural alignment to shift it into 16 bits. If you
|
||||
// set a memory_map function, you must also set a memory_unmap function or
|
||||
// else the default implementation will be used for both. This function must
|
||||
// be thread safe, it can be called by multiple threads simultaneously.
|
||||
void *(*memory_map)(size_t size, size_t *offset);
|
||||
//! Unmap the memory pages starting at address and spanning the given number
|
||||
//! of bytes.
|
||||
// If release is set to non-zero, the unmap is for an entire span range as
|
||||
// returned by a previous call to memory_map and that the entire range should
|
||||
// be released. The release argument holds the size of the entire span range.
|
||||
// If release is set to 0, the unmap is a partial decommit of a subset of the
|
||||
// mapped memory range. If you set a memory_unmap function, you must also set
|
||||
// a memory_map function or else the default implementation will be used for
|
||||
// both. This function must be thread safe, it can be called by multiple
|
||||
// threads simultaneously.
|
||||
void (*memory_unmap)(void *address, size_t size, size_t offset,
|
||||
size_t release);
|
||||
//! Called when an assert fails, if asserts are enabled. Will use the standard
|
||||
//! assert()
|
||||
// if this is not set.
|
||||
void (*error_callback)(const char *message);
|
||||
//! Called when a call to map memory pages fails (out of memory). If this
|
||||
//! callback is
|
||||
// not set or returns zero the library will return a null pointer in the
|
||||
// allocation call. If this callback returns non-zero the map call will be
|
||||
// retried. The argument passed is the number of bytes that was requested in
|
||||
// the map call. Only used if the default system memory map function is used
|
||||
// (memory_map callback is not set).
|
||||
int (*map_fail_callback)(size_t size);
|
||||
//! Size of memory pages. The page size MUST be a power of two. All memory
|
||||
//! mapping
|
||||
// requests to memory_map will be made with size set to a multiple of the
|
||||
// page size. Used if RPMALLOC_CONFIGURABLE is defined to 1, otherwise system
|
||||
// page size is used.
|
||||
size_t page_size;
|
||||
//! Size of a span of memory blocks. MUST be a power of two, and in
|
||||
//! [4096,262144]
|
||||
// range (unless 0 - set to 0 to use the default span size). Used if
|
||||
// RPMALLOC_CONFIGURABLE is defined to 1.
|
||||
size_t span_size;
|
||||
//! Number of spans to map at each request to map new virtual memory blocks.
|
||||
//! This can
|
||||
// be used to minimize the system call overhead at the cost of virtual memory
|
||||
// address space. The extra mapped pages will not be written until actually
|
||||
// used, so physical committed memory should not be affected in the default
|
||||
// implementation. Will be aligned to a multiple of spans that match memory
|
||||
// page size in case of huge pages.
|
||||
size_t span_map_count;
|
||||
//! Enable use of large/huge pages. If this flag is set to non-zero and page
|
||||
//! size is
|
||||
// zero, the allocator will try to enable huge pages and auto detect the
|
||||
// configuration. If this is set to non-zero and page_size is also non-zero,
|
||||
// the allocator will assume huge pages have been configured and enabled
|
||||
// prior to initializing the allocator. For Windows, see
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/memory/large-page-support
|
||||
// For Linux, see https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt
|
||||
int enable_huge_pages;
|
||||
//! Respectively allocated pages and huge allocated pages names for systems
|
||||
// supporting it to be able to distinguish among anonymous regions.
|
||||
const char *page_name;
|
||||
const char *huge_page_name;
|
||||
} rpmalloc_config_t;
|
||||
|
||||
//! Initialize allocator with default configuration
|
||||
RPMALLOC_EXPORT int rpmalloc_initialize(void);
|
||||
|
||||
//! Initialize allocator with given configuration
|
||||
RPMALLOC_EXPORT int rpmalloc_initialize_config(const rpmalloc_config_t *config);
|
||||
|
||||
//! Get allocator configuration
|
||||
RPMALLOC_EXPORT const rpmalloc_config_t *rpmalloc_config(void);
|
||||
|
||||
//! Finalize allocator
|
||||
RPMALLOC_EXPORT void rpmalloc_finalize(void);
|
||||
|
||||
//! Initialize allocator for calling thread
|
||||
RPMALLOC_EXPORT void rpmalloc_thread_initialize(void);
|
||||
|
||||
//! Finalize allocator for calling thread
|
||||
RPMALLOC_EXPORT void rpmalloc_thread_finalize(int release_caches);
|
||||
|
||||
//! Perform deferred deallocations pending for the calling thread heap
|
||||
RPMALLOC_EXPORT void rpmalloc_thread_collect(void);
|
||||
|
||||
//! Query if allocator is initialized for calling thread
|
||||
RPMALLOC_EXPORT int rpmalloc_is_thread_initialized(void);
|
||||
|
||||
//! Get per-thread statistics
|
||||
RPMALLOC_EXPORT void
|
||||
rpmalloc_thread_statistics(rpmalloc_thread_statistics_t *stats);
|
||||
|
||||
//! Get global statistics
|
||||
RPMALLOC_EXPORT void
|
||||
rpmalloc_global_statistics(rpmalloc_global_statistics_t *stats);
|
||||
|
||||
//! Dump all statistics in human readable format to file (should be a FILE*)
|
||||
RPMALLOC_EXPORT void rpmalloc_dump_statistics(void *file);
|
||||
|
||||
//! Allocate a memory block of at least the given size
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc(size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1);
|
||||
|
||||
//! Free the given memory block
|
||||
RPMALLOC_EXPORT void rpfree(void *ptr);
|
||||
|
||||
//! Allocate a memory block of at least the given size and zero initialize it
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpcalloc(size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE2(1, 2);
|
||||
|
||||
//! Reallocate the given block to at least the given size
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rprealloc(void *ptr, size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
||||
|
||||
//! Reallocate the given block to at least the given size and alignment,
|
||||
// with optional control flags (see RPMALLOC_NO_PRESERVE).
|
||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size
|
||||
// (default 64KiB)
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpaligned_realloc(void *ptr, size_t alignment, size_t size, size_t oldsize,
|
||||
unsigned int flags) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE(3);
|
||||
|
||||
//! Allocate a memory block of at least the given size and alignment.
|
||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size
|
||||
// (default 64KiB)
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpaligned_alloc(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
||||
|
||||
//! Allocate a memory block of at least the given size and alignment, and zero
|
||||
//! initialize it.
|
||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size
|
||||
// (default 64KiB)
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpaligned_calloc(size_t alignment, size_t num,
|
||||
size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
|
||||
|
||||
//! Allocate a memory block of at least the given size and alignment.
|
||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size
|
||||
// (default 64KiB)
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmemalign(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
||||
|
||||
//! Allocate a memory block of at least the given size and alignment.
|
||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size
|
||||
// (default 64KiB)
|
||||
RPMALLOC_EXPORT int rpposix_memalign(void **memptr, size_t alignment,
|
||||
size_t size);
|
||||
|
||||
//! Query the usable size of the given memory block (from given pointer to the
|
||||
//! end of block)
|
||||
RPMALLOC_EXPORT size_t rpmalloc_usable_size(void *ptr);
|
||||
|
||||
//! Dummy empty function for forcing linker symbol inclusion
|
||||
RPMALLOC_EXPORT void rpmalloc_linker_reference(void);
|
||||
|
||||
#if RPMALLOC_FIRST_CLASS_HEAPS
|
||||
|
||||
//! Heap type
|
||||
typedef struct heap_t rpmalloc_heap_t;
|
||||
|
||||
//! Acquire a new heap. Will reuse existing released heaps or allocate memory
|
||||
//! for a new heap
|
||||
// if none available. Heap API is implemented with the strict assumption that
|
||||
// only one single thread will call heap functions for a given heap at any
|
||||
// given time, no functions are thread safe.
|
||||
RPMALLOC_EXPORT rpmalloc_heap_t *rpmalloc_heap_acquire(void);
|
||||
|
||||
//! Release a heap (does NOT free the memory allocated by the heap, use
|
||||
//! rpmalloc_heap_free_all before destroying the heap).
|
||||
// Releasing a heap will enable it to be reused by other threads. Safe to pass
|
||||
// a null pointer.
|
||||
RPMALLOC_EXPORT void rpmalloc_heap_release(rpmalloc_heap_t *heap);
|
||||
|
||||
//! Allocate a memory block of at least the given size using the given heap.
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc_heap_alloc(rpmalloc_heap_t *heap, size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
||||
|
||||
//! Allocate a memory block of at least the given size using the given heap. The
|
||||
//! returned
|
||||
// block will have the requested alignment. Alignment must be a power of two
|
||||
// and a multiple of sizeof(void*), and should ideally be less than memory page
|
||||
// size. A caveat of rpmalloc internals is that this must also be strictly less
|
||||
// than the span size (default 64KiB).
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc_heap_aligned_alloc(rpmalloc_heap_t *heap, size_t alignment,
|
||||
size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE(3);
|
||||
|
||||
//! Allocate a memory block of at least the given size using the given heap and
|
||||
//! zero initialize it.
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc_heap_calloc(rpmalloc_heap_t *heap, size_t num,
|
||||
size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
|
||||
|
||||
//! Allocate a memory block of at least the given size using the given heap and
|
||||
//! zero initialize it. The returned
|
||||
// block will have the requested alignment. Alignment must either be zero, or a
|
||||
// power of two and a multiple of sizeof(void*), and should ideally be less
|
||||
// than memory page size. A caveat of rpmalloc internals is that this must also
|
||||
// be strictly less than the span size (default 64KiB).
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc_heap_aligned_calloc(rpmalloc_heap_t *heap, size_t alignment,
|
||||
size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
|
||||
|
||||
//! Reallocate the given block to at least the given size. The memory block MUST
|
||||
//! be allocated
|
||||
// by the same heap given to this function.
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc_heap_realloc(rpmalloc_heap_t *heap, void *ptr, size_t size,
|
||||
unsigned int flags) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE(3);
|
||||
|
||||
//! Reallocate the given block to at least the given size. The memory block MUST
|
||||
//! be allocated
|
||||
// by the same heap given to this function. The returned block will have the
|
||||
// requested alignment. Alignment must be either zero, or a power of two and a
|
||||
// multiple of sizeof(void*), and should ideally be less than memory page size.
|
||||
// A caveat of rpmalloc internals is that this must also be strictly less than
|
||||
// the span size (default 64KiB).
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *rpmalloc_heap_aligned_realloc(
|
||||
rpmalloc_heap_t *heap, void *ptr, size_t alignment, size_t size,
|
||||
unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(4);
|
||||
|
||||
//! Free the given memory block from the given heap. The memory block MUST be
|
||||
//! allocated
|
||||
// by the same heap given to this function.
|
||||
RPMALLOC_EXPORT void rpmalloc_heap_free(rpmalloc_heap_t *heap, void *ptr);
|
||||
|
||||
//! Free all memory allocated by the heap
|
||||
RPMALLOC_EXPORT void rpmalloc_heap_free_all(rpmalloc_heap_t *heap);
|
||||
|
||||
//! Set the given heap as the current heap for the calling thread. A heap MUST
|
||||
//! only be current heap
|
||||
// for a single thread, a heap can never be shared between multiple threads.
|
||||
// The previous current heap for the calling thread is released to be reused by
|
||||
// other threads.
|
||||
RPMALLOC_EXPORT void rpmalloc_heap_thread_set_current(rpmalloc_heap_t *heap);
|
||||
|
||||
//! Returns which heap the given pointer is allocated on
|
||||
RPMALLOC_EXPORT rpmalloc_heap_t *rpmalloc_get_heap_for_ptr(void *ptr);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
//===---------------------- rpmalloc.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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This library provides a cross-platform lock free thread caching malloc
|
||||
// implementation in C11.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#define RPMALLOC_EXPORT __attribute__((visibility("default")))
|
||||
#define RPMALLOC_ALLOCATOR
|
||||
#if (defined(__clang_major__) && (__clang_major__ < 4)) || \
|
||||
(defined(__GNUC__) && defined(ENABLE_PRELOAD) && ENABLE_PRELOAD)
|
||||
#define RPMALLOC_ATTRIB_MALLOC
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size)
|
||||
#else
|
||||
#define RPMALLOC_ATTRIB_MALLOC __attribute__((__malloc__))
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE(size) __attribute__((alloc_size(size)))
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size) \
|
||||
__attribute__((alloc_size(count, size)))
|
||||
#endif
|
||||
#define RPMALLOC_CDECL
|
||||
#elif defined(_MSC_VER)
|
||||
#define RPMALLOC_EXPORT
|
||||
#define RPMALLOC_ALLOCATOR __declspec(allocator) __declspec(restrict)
|
||||
#define RPMALLOC_ATTRIB_MALLOC
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size)
|
||||
#define RPMALLOC_CDECL __cdecl
|
||||
#else
|
||||
#define RPMALLOC_EXPORT
|
||||
#define RPMALLOC_ALLOCATOR
|
||||
#define RPMALLOC_ATTRIB_MALLOC
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
|
||||
#define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size)
|
||||
#define RPMALLOC_CDECL
|
||||
#endif
|
||||
|
||||
//! Define RPMALLOC_CONFIGURABLE to enable configuring sizes. Will introduce
|
||||
// a very small overhead due to some size calculations not being compile time
|
||||
// constants
|
||||
#ifndef RPMALLOC_CONFIGURABLE
|
||||
#define RPMALLOC_CONFIGURABLE 0
|
||||
#endif
|
||||
|
||||
//! Define RPMALLOC_FIRST_CLASS_HEAPS to enable heap based API (rpmalloc_heap_*
|
||||
//! functions).
|
||||
// Will introduce a very small overhead to track fully allocated spans in heaps
|
||||
#ifndef RPMALLOC_FIRST_CLASS_HEAPS
|
||||
#define RPMALLOC_FIRST_CLASS_HEAPS 0
|
||||
#endif
|
||||
|
||||
//! Flag to rpaligned_realloc to not preserve content in reallocation
|
||||
#define RPMALLOC_NO_PRESERVE 1
|
||||
//! Flag to rpaligned_realloc to fail and return null pointer if grow cannot be
|
||||
//! done in-place,
|
||||
// in which case the original pointer is still valid (just like a call to
|
||||
// realloc which failes to allocate a new block).
|
||||
#define RPMALLOC_GROW_OR_FAIL 2
|
||||
|
||||
typedef struct rpmalloc_global_statistics_t {
|
||||
//! Current amount of virtual memory mapped, all of which might not have been
|
||||
//! committed (only if ENABLE_STATISTICS=1)
|
||||
size_t mapped;
|
||||
//! Peak amount of virtual memory mapped, all of which might not have been
|
||||
//! committed (only if ENABLE_STATISTICS=1)
|
||||
size_t mapped_peak;
|
||||
//! Current amount of memory in global caches for small and medium sizes
|
||||
//! (<32KiB)
|
||||
size_t cached;
|
||||
//! Current amount of memory allocated in huge allocations, i.e larger than
|
||||
//! LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1)
|
||||
size_t huge_alloc;
|
||||
//! Peak amount of memory allocated in huge allocations, i.e larger than
|
||||
//! LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1)
|
||||
size_t huge_alloc_peak;
|
||||
//! Total amount of memory mapped since initialization (only if
|
||||
//! ENABLE_STATISTICS=1)
|
||||
size_t mapped_total;
|
||||
//! Total amount of memory unmapped since initialization (only if
|
||||
//! ENABLE_STATISTICS=1)
|
||||
size_t unmapped_total;
|
||||
} rpmalloc_global_statistics_t;
|
||||
|
||||
typedef struct rpmalloc_thread_statistics_t {
|
||||
//! Current number of bytes available in thread size class caches for small
|
||||
//! and medium sizes (<32KiB)
|
||||
size_t sizecache;
|
||||
//! Current number of bytes available in thread span caches for small and
|
||||
//! medium sizes (<32KiB)
|
||||
size_t spancache;
|
||||
//! Total number of bytes transitioned from thread cache to global cache (only
|
||||
//! if ENABLE_STATISTICS=1)
|
||||
size_t thread_to_global;
|
||||
//! Total number of bytes transitioned from global cache to thread cache (only
|
||||
//! if ENABLE_STATISTICS=1)
|
||||
size_t global_to_thread;
|
||||
//! Per span count statistics (only if ENABLE_STATISTICS=1)
|
||||
struct {
|
||||
//! Currently used number of spans
|
||||
size_t current;
|
||||
//! High water mark of spans used
|
||||
size_t peak;
|
||||
//! Number of spans transitioned to global cache
|
||||
size_t to_global;
|
||||
//! Number of spans transitioned from global cache
|
||||
size_t from_global;
|
||||
//! Number of spans transitioned to thread cache
|
||||
size_t to_cache;
|
||||
//! Number of spans transitioned from thread cache
|
||||
size_t from_cache;
|
||||
//! Number of spans transitioned to reserved state
|
||||
size_t to_reserved;
|
||||
//! Number of spans transitioned from reserved state
|
||||
size_t from_reserved;
|
||||
//! Number of raw memory map calls (not hitting the reserve spans but
|
||||
//! resulting in actual OS mmap calls)
|
||||
size_t map_calls;
|
||||
} span_use[64];
|
||||
//! Per size class statistics (only if ENABLE_STATISTICS=1)
|
||||
struct {
|
||||
//! Current number of allocations
|
||||
size_t alloc_current;
|
||||
//! Peak number of allocations
|
||||
size_t alloc_peak;
|
||||
//! Total number of allocations
|
||||
size_t alloc_total;
|
||||
//! Total number of frees
|
||||
size_t free_total;
|
||||
//! Number of spans transitioned to cache
|
||||
size_t spans_to_cache;
|
||||
//! Number of spans transitioned from cache
|
||||
size_t spans_from_cache;
|
||||
//! Number of spans transitioned from reserved state
|
||||
size_t spans_from_reserved;
|
||||
//! Number of raw memory map calls (not hitting the reserve spans but
|
||||
//! resulting in actual OS mmap calls)
|
||||
size_t map_calls;
|
||||
} size_use[128];
|
||||
} rpmalloc_thread_statistics_t;
|
||||
|
||||
typedef struct rpmalloc_config_t {
|
||||
//! Map memory pages for the given number of bytes. The returned address MUST
|
||||
//! be
|
||||
// aligned to the rpmalloc span size, which will always be a power of two.
|
||||
// Optionally the function can store an alignment offset in the offset
|
||||
// variable in case it performs alignment and the returned pointer is offset
|
||||
// from the actual start of the memory region due to this alignment. The
|
||||
// alignment offset will be passed to the memory unmap function. The
|
||||
// alignment offset MUST NOT be larger than 65535 (storable in an uint16_t),
|
||||
// if it is you must use natural alignment to shift it into 16 bits. If you
|
||||
// set a memory_map function, you must also set a memory_unmap function or
|
||||
// else the default implementation will be used for both. This function must
|
||||
// be thread safe, it can be called by multiple threads simultaneously.
|
||||
void *(*memory_map)(size_t size, size_t *offset);
|
||||
//! Unmap the memory pages starting at address and spanning the given number
|
||||
//! of bytes.
|
||||
// If release is set to non-zero, the unmap is for an entire span range as
|
||||
// returned by a previous call to memory_map and that the entire range should
|
||||
// be released. The release argument holds the size of the entire span range.
|
||||
// If release is set to 0, the unmap is a partial decommit of a subset of the
|
||||
// mapped memory range. If you set a memory_unmap function, you must also set
|
||||
// a memory_map function or else the default implementation will be used for
|
||||
// both. This function must be thread safe, it can be called by multiple
|
||||
// threads simultaneously.
|
||||
void (*memory_unmap)(void *address, size_t size, size_t offset,
|
||||
size_t release);
|
||||
//! Called when an assert fails, if asserts are enabled. Will use the standard
|
||||
//! assert()
|
||||
// if this is not set.
|
||||
void (*error_callback)(const char *message);
|
||||
//! Called when a call to map memory pages fails (out of memory). If this
|
||||
//! callback is
|
||||
// not set or returns zero the library will return a null pointer in the
|
||||
// allocation call. If this callback returns non-zero the map call will be
|
||||
// retried. The argument passed is the number of bytes that was requested in
|
||||
// the map call. Only used if the default system memory map function is used
|
||||
// (memory_map callback is not set).
|
||||
int (*map_fail_callback)(size_t size);
|
||||
//! Size of memory pages. The page size MUST be a power of two. All memory
|
||||
//! mapping
|
||||
// requests to memory_map will be made with size set to a multiple of the
|
||||
// page size. Used if RPMALLOC_CONFIGURABLE is defined to 1, otherwise system
|
||||
// page size is used.
|
||||
size_t page_size;
|
||||
//! Size of a span of memory blocks. MUST be a power of two, and in
|
||||
//! [4096,262144]
|
||||
// range (unless 0 - set to 0 to use the default span size). Used if
|
||||
// RPMALLOC_CONFIGURABLE is defined to 1.
|
||||
size_t span_size;
|
||||
//! Number of spans to map at each request to map new virtual memory blocks.
|
||||
//! This can
|
||||
// be used to minimize the system call overhead at the cost of virtual memory
|
||||
// address space. The extra mapped pages will not be written until actually
|
||||
// used, so physical committed memory should not be affected in the default
|
||||
// implementation. Will be aligned to a multiple of spans that match memory
|
||||
// page size in case of huge pages.
|
||||
size_t span_map_count;
|
||||
//! Enable use of large/huge pages. If this flag is set to non-zero and page
|
||||
//! size is
|
||||
// zero, the allocator will try to enable huge pages and auto detect the
|
||||
// configuration. If this is set to non-zero and page_size is also non-zero,
|
||||
// the allocator will assume huge pages have been configured and enabled
|
||||
// prior to initializing the allocator. For Windows, see
|
||||
// https://docs.microsoft.com/en-us/windows/desktop/memory/large-page-support
|
||||
// For Linux, see https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt
|
||||
int enable_huge_pages;
|
||||
//! Respectively allocated pages and huge allocated pages names for systems
|
||||
// supporting it to be able to distinguish among anonymous regions.
|
||||
const char *page_name;
|
||||
const char *huge_page_name;
|
||||
} rpmalloc_config_t;
|
||||
|
||||
//! Initialize allocator with default configuration
|
||||
RPMALLOC_EXPORT int rpmalloc_initialize(void);
|
||||
|
||||
//! Initialize allocator with given configuration
|
||||
RPMALLOC_EXPORT int rpmalloc_initialize_config(const rpmalloc_config_t *config);
|
||||
|
||||
//! Get allocator configuration
|
||||
RPMALLOC_EXPORT const rpmalloc_config_t *rpmalloc_config(void);
|
||||
|
||||
//! Finalize allocator
|
||||
RPMALLOC_EXPORT void rpmalloc_finalize(void);
|
||||
|
||||
//! Initialize allocator for calling thread
|
||||
RPMALLOC_EXPORT void rpmalloc_thread_initialize(void);
|
||||
|
||||
//! Finalize allocator for calling thread
|
||||
RPMALLOC_EXPORT void rpmalloc_thread_finalize(int release_caches);
|
||||
|
||||
//! Perform deferred deallocations pending for the calling thread heap
|
||||
RPMALLOC_EXPORT void rpmalloc_thread_collect(void);
|
||||
|
||||
//! Query if allocator is initialized for calling thread
|
||||
RPMALLOC_EXPORT int rpmalloc_is_thread_initialized(void);
|
||||
|
||||
//! Get per-thread statistics
|
||||
RPMALLOC_EXPORT void
|
||||
rpmalloc_thread_statistics(rpmalloc_thread_statistics_t *stats);
|
||||
|
||||
//! Get global statistics
|
||||
RPMALLOC_EXPORT void
|
||||
rpmalloc_global_statistics(rpmalloc_global_statistics_t *stats);
|
||||
|
||||
//! Dump all statistics in human readable format to file (should be a FILE*)
|
||||
RPMALLOC_EXPORT void rpmalloc_dump_statistics(void *file);
|
||||
|
||||
//! Allocate a memory block of at least the given size
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc(size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1);
|
||||
|
||||
//! Free the given memory block
|
||||
RPMALLOC_EXPORT void rpfree(void *ptr);
|
||||
|
||||
//! Allocate a memory block of at least the given size and zero initialize it
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpcalloc(size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE2(1, 2);
|
||||
|
||||
//! Reallocate the given block to at least the given size
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rprealloc(void *ptr, size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
||||
|
||||
//! Reallocate the given block to at least the given size and alignment,
|
||||
// with optional control flags (see RPMALLOC_NO_PRESERVE).
|
||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size
|
||||
// (default 64KiB)
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpaligned_realloc(void *ptr, size_t alignment, size_t size, size_t oldsize,
|
||||
unsigned int flags) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE(3);
|
||||
|
||||
//! Allocate a memory block of at least the given size and alignment.
|
||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size
|
||||
// (default 64KiB)
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpaligned_alloc(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
||||
|
||||
//! Allocate a memory block of at least the given size and alignment, and zero
|
||||
//! initialize it.
|
||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size
|
||||
// (default 64KiB)
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpaligned_calloc(size_t alignment, size_t num,
|
||||
size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
|
||||
|
||||
//! Allocate a memory block of at least the given size and alignment.
|
||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size
|
||||
// (default 64KiB)
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmemalign(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
||||
|
||||
//! Allocate a memory block of at least the given size and alignment.
|
||||
// Alignment must be a power of two and a multiple of sizeof(void*),
|
||||
// and should ideally be less than memory page size. A caveat of rpmalloc
|
||||
// internals is that this must also be strictly less than the span size
|
||||
// (default 64KiB)
|
||||
RPMALLOC_EXPORT int rpposix_memalign(void **memptr, size_t alignment,
|
||||
size_t size);
|
||||
|
||||
//! Query the usable size of the given memory block (from given pointer to the
|
||||
//! end of block)
|
||||
RPMALLOC_EXPORT size_t rpmalloc_usable_size(void *ptr);
|
||||
|
||||
//! Dummy empty function for forcing linker symbol inclusion
|
||||
RPMALLOC_EXPORT void rpmalloc_linker_reference(void);
|
||||
|
||||
#if RPMALLOC_FIRST_CLASS_HEAPS
|
||||
|
||||
//! Heap type
|
||||
typedef struct heap_t rpmalloc_heap_t;
|
||||
|
||||
//! Acquire a new heap. Will reuse existing released heaps or allocate memory
|
||||
//! for a new heap
|
||||
// if none available. Heap API is implemented with the strict assumption that
|
||||
// only one single thread will call heap functions for a given heap at any
|
||||
// given time, no functions are thread safe.
|
||||
RPMALLOC_EXPORT rpmalloc_heap_t *rpmalloc_heap_acquire(void);
|
||||
|
||||
//! Release a heap (does NOT free the memory allocated by the heap, use
|
||||
//! rpmalloc_heap_free_all before destroying the heap).
|
||||
// Releasing a heap will enable it to be reused by other threads. Safe to pass
|
||||
// a null pointer.
|
||||
RPMALLOC_EXPORT void rpmalloc_heap_release(rpmalloc_heap_t *heap);
|
||||
|
||||
//! Allocate a memory block of at least the given size using the given heap.
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc_heap_alloc(rpmalloc_heap_t *heap, size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE(2);
|
||||
|
||||
//! Allocate a memory block of at least the given size using the given heap. The
|
||||
//! returned
|
||||
// block will have the requested alignment. Alignment must be a power of two
|
||||
// and a multiple of sizeof(void*), and should ideally be less than memory page
|
||||
// size. A caveat of rpmalloc internals is that this must also be strictly less
|
||||
// than the span size (default 64KiB).
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc_heap_aligned_alloc(rpmalloc_heap_t *heap, size_t alignment,
|
||||
size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE(3);
|
||||
|
||||
//! Allocate a memory block of at least the given size using the given heap and
|
||||
//! zero initialize it.
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc_heap_calloc(rpmalloc_heap_t *heap, size_t num,
|
||||
size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
|
||||
|
||||
//! Allocate a memory block of at least the given size using the given heap and
|
||||
//! zero initialize it. The returned
|
||||
// block will have the requested alignment. Alignment must either be zero, or a
|
||||
// power of two and a multiple of sizeof(void*), and should ideally be less
|
||||
// than memory page size. A caveat of rpmalloc internals is that this must also
|
||||
// be strictly less than the span size (default 64KiB).
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc_heap_aligned_calloc(rpmalloc_heap_t *heap, size_t alignment,
|
||||
size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3);
|
||||
|
||||
//! Reallocate the given block to at least the given size. The memory block MUST
|
||||
//! be allocated
|
||||
// by the same heap given to this function.
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *
|
||||
rpmalloc_heap_realloc(rpmalloc_heap_t *heap, void *ptr, size_t size,
|
||||
unsigned int flags) RPMALLOC_ATTRIB_MALLOC
|
||||
RPMALLOC_ATTRIB_ALLOC_SIZE(3);
|
||||
|
||||
//! Reallocate the given block to at least the given size. The memory block MUST
|
||||
//! be allocated
|
||||
// by the same heap given to this function. The returned block will have the
|
||||
// requested alignment. Alignment must be either zero, or a power of two and a
|
||||
// multiple of sizeof(void*), and should ideally be less than memory page size.
|
||||
// A caveat of rpmalloc internals is that this must also be strictly less than
|
||||
// the span size (default 64KiB).
|
||||
RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void *rpmalloc_heap_aligned_realloc(
|
||||
rpmalloc_heap_t *heap, void *ptr, size_t alignment, size_t size,
|
||||
unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(4);
|
||||
|
||||
//! Free the given memory block from the given heap. The memory block MUST be
|
||||
//! allocated
|
||||
// by the same heap given to this function.
|
||||
RPMALLOC_EXPORT void rpmalloc_heap_free(rpmalloc_heap_t *heap, void *ptr);
|
||||
|
||||
//! Free all memory allocated by the heap
|
||||
RPMALLOC_EXPORT void rpmalloc_heap_free_all(rpmalloc_heap_t *heap);
|
||||
|
||||
//! Set the given heap as the current heap for the calling thread. A heap MUST
|
||||
//! only be current heap
|
||||
// for a single thread, a heap can never be shared between multiple threads.
|
||||
// The previous current heap for the calling thread is released to be reused by
|
||||
// other threads.
|
||||
RPMALLOC_EXPORT void rpmalloc_heap_thread_set_current(rpmalloc_heap_t *heap);
|
||||
|
||||
//! Returns which heap the given pointer is allocated on
|
||||
RPMALLOC_EXPORT rpmalloc_heap_t *rpmalloc_get_heap_for_ptr(void *ptr);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,113 +1,113 @@
|
||||
//===-------------------------- rpnew.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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This library provides a cross-platform lock free thread caching malloc
|
||||
// implementation in C11.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <new>
|
||||
#include <rpmalloc.h>
|
||||
|
||||
#ifndef __CRTDECL
|
||||
#define __CRTDECL
|
||||
#endif
|
||||
|
||||
extern void __CRTDECL operator delete(void *p) noexcept { rpfree(p); }
|
||||
|
||||
extern void __CRTDECL operator delete[](void *p) noexcept { rpfree(p); }
|
||||
|
||||
extern void *__CRTDECL operator new(std::size_t size) noexcept(false) {
|
||||
return rpmalloc(size);
|
||||
}
|
||||
|
||||
extern void *__CRTDECL operator new[](std::size_t size) noexcept(false) {
|
||||
return rpmalloc(size);
|
||||
}
|
||||
|
||||
extern void *__CRTDECL operator new(std::size_t size,
|
||||
const std::nothrow_t &tag) noexcept {
|
||||
(void)sizeof(tag);
|
||||
return rpmalloc(size);
|
||||
}
|
||||
|
||||
extern void *__CRTDECL operator new[](std::size_t size,
|
||||
const std::nothrow_t &tag) noexcept {
|
||||
(void)sizeof(tag);
|
||||
return rpmalloc(size);
|
||||
}
|
||||
|
||||
#if (__cplusplus >= 201402L || _MSC_VER >= 1916)
|
||||
|
||||
extern void __CRTDECL operator delete(void *p, std::size_t size) noexcept {
|
||||
(void)sizeof(size);
|
||||
rpfree(p);
|
||||
}
|
||||
|
||||
extern void __CRTDECL operator delete[](void *p, std::size_t size) noexcept {
|
||||
(void)sizeof(size);
|
||||
rpfree(p);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (__cplusplus > 201402L || defined(__cpp_aligned_new))
|
||||
|
||||
extern void __CRTDECL operator delete(void *p,
|
||||
std::align_val_t align) noexcept {
|
||||
(void)sizeof(align);
|
||||
rpfree(p);
|
||||
}
|
||||
|
||||
extern void __CRTDECL operator delete[](void *p,
|
||||
std::align_val_t align) noexcept {
|
||||
(void)sizeof(align);
|
||||
rpfree(p);
|
||||
}
|
||||
|
||||
extern void __CRTDECL operator delete(void *p, std::size_t size,
|
||||
std::align_val_t align) noexcept {
|
||||
(void)sizeof(size);
|
||||
(void)sizeof(align);
|
||||
rpfree(p);
|
||||
}
|
||||
|
||||
extern void __CRTDECL operator delete[](void *p, std::size_t size,
|
||||
std::align_val_t align) noexcept {
|
||||
(void)sizeof(size);
|
||||
(void)sizeof(align);
|
||||
rpfree(p);
|
||||
}
|
||||
|
||||
extern void *__CRTDECL operator new(std::size_t size,
|
||||
std::align_val_t align) noexcept(false) {
|
||||
return rpaligned_alloc(static_cast<size_t>(align), size);
|
||||
}
|
||||
|
||||
extern void *__CRTDECL operator new[](std::size_t size,
|
||||
std::align_val_t align) noexcept(false) {
|
||||
return rpaligned_alloc(static_cast<size_t>(align), size);
|
||||
}
|
||||
|
||||
extern void *__CRTDECL operator new(std::size_t size, std::align_val_t align,
|
||||
const std::nothrow_t &tag) noexcept {
|
||||
(void)sizeof(tag);
|
||||
return rpaligned_alloc(static_cast<size_t>(align), size);
|
||||
}
|
||||
|
||||
extern void *__CRTDECL operator new[](std::size_t size, std::align_val_t align,
|
||||
const std::nothrow_t &tag) noexcept {
|
||||
(void)sizeof(tag);
|
||||
return rpaligned_alloc(static_cast<size_t>(align), size);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
//===-------------------------- rpnew.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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This library provides a cross-platform lock free thread caching malloc
|
||||
// implementation in C11.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <new>
|
||||
#include <rpmalloc.h>
|
||||
|
||||
#ifndef __CRTDECL
|
||||
#define __CRTDECL
|
||||
#endif
|
||||
|
||||
extern void __CRTDECL operator delete(void *p) noexcept { rpfree(p); }
|
||||
|
||||
extern void __CRTDECL operator delete[](void *p) noexcept { rpfree(p); }
|
||||
|
||||
extern void *__CRTDECL operator new(std::size_t size) noexcept(false) {
|
||||
return rpmalloc(size);
|
||||
}
|
||||
|
||||
extern void *__CRTDECL operator new[](std::size_t size) noexcept(false) {
|
||||
return rpmalloc(size);
|
||||
}
|
||||
|
||||
extern void *__CRTDECL operator new(std::size_t size,
|
||||
const std::nothrow_t &tag) noexcept {
|
||||
(void)sizeof(tag);
|
||||
return rpmalloc(size);
|
||||
}
|
||||
|
||||
extern void *__CRTDECL operator new[](std::size_t size,
|
||||
const std::nothrow_t &tag) noexcept {
|
||||
(void)sizeof(tag);
|
||||
return rpmalloc(size);
|
||||
}
|
||||
|
||||
#if (__cplusplus >= 201402L || _MSC_VER >= 1916)
|
||||
|
||||
extern void __CRTDECL operator delete(void *p, std::size_t size) noexcept {
|
||||
(void)sizeof(size);
|
||||
rpfree(p);
|
||||
}
|
||||
|
||||
extern void __CRTDECL operator delete[](void *p, std::size_t size) noexcept {
|
||||
(void)sizeof(size);
|
||||
rpfree(p);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if (__cplusplus > 201402L || defined(__cpp_aligned_new))
|
||||
|
||||
extern void __CRTDECL operator delete(void *p,
|
||||
std::align_val_t align) noexcept {
|
||||
(void)sizeof(align);
|
||||
rpfree(p);
|
||||
}
|
||||
|
||||
extern void __CRTDECL operator delete[](void *p,
|
||||
std::align_val_t align) noexcept {
|
||||
(void)sizeof(align);
|
||||
rpfree(p);
|
||||
}
|
||||
|
||||
extern void __CRTDECL operator delete(void *p, std::size_t size,
|
||||
std::align_val_t align) noexcept {
|
||||
(void)sizeof(size);
|
||||
(void)sizeof(align);
|
||||
rpfree(p);
|
||||
}
|
||||
|
||||
extern void __CRTDECL operator delete[](void *p, std::size_t size,
|
||||
std::align_val_t align) noexcept {
|
||||
(void)sizeof(size);
|
||||
(void)sizeof(align);
|
||||
rpfree(p);
|
||||
}
|
||||
|
||||
extern void *__CRTDECL operator new(std::size_t size,
|
||||
std::align_val_t align) noexcept(false) {
|
||||
return rpaligned_alloc(static_cast<size_t>(align), size);
|
||||
}
|
||||
|
||||
extern void *__CRTDECL operator new[](std::size_t size,
|
||||
std::align_val_t align) noexcept(false) {
|
||||
return rpaligned_alloc(static_cast<size_t>(align), size);
|
||||
}
|
||||
|
||||
extern void *__CRTDECL operator new(std::size_t size, std::align_val_t align,
|
||||
const std::nothrow_t &tag) noexcept {
|
||||
(void)sizeof(tag);
|
||||
return rpaligned_alloc(static_cast<size_t>(align), size);
|
||||
}
|
||||
|
||||
extern void *__CRTDECL operator new[](std::size_t size, std::align_val_t align,
|
||||
const std::nothrow_t &tag) noexcept {
|
||||
(void)sizeof(tag);
|
||||
return rpaligned_alloc(static_cast<size_t>(align), size);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,38 +1,38 @@
|
||||
//===- DirectXTargetTransformInfo.cpp - DirectX TTI ---------------*- 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 "DirectXTargetTransformInfo.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/IntrinsicsDirectX.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
bool DirectXTTIImpl::isTargetIntrinsicWithScalarOpAtArg(Intrinsic::ID ID,
|
||||
unsigned ScalarOpdIdx) {
|
||||
switch (ID) {
|
||||
case Intrinsic::dx_wave_readlane:
|
||||
return ScalarOpdIdx == 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DirectXTTIImpl::isTargetIntrinsicTriviallyScalarizable(
|
||||
Intrinsic::ID ID) const {
|
||||
switch (ID) {
|
||||
case Intrinsic::dx_frac:
|
||||
case Intrinsic::dx_rsqrt:
|
||||
case Intrinsic::dx_wave_readlane:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//===- DirectXTargetTransformInfo.cpp - DirectX TTI ---------------*- 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 "DirectXTargetTransformInfo.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/IntrinsicsDirectX.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
bool DirectXTTIImpl::isTargetIntrinsicWithScalarOpAtArg(Intrinsic::ID ID,
|
||||
unsigned ScalarOpdIdx) {
|
||||
switch (ID) {
|
||||
case Intrinsic::dx_wave_readlane:
|
||||
return ScalarOpdIdx == 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DirectXTTIImpl::isTargetIntrinsicTriviallyScalarizable(
|
||||
Intrinsic::ID ID) const {
|
||||
switch (ID) {
|
||||
case Intrinsic::dx_frac:
|
||||
case Intrinsic::dx_rsqrt:
|
||||
case Intrinsic::dx_wave_readlane:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,87 +1,87 @@
|
||||
; RUN: opt -S -dxil-intrinsic-expansion -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
|
||||
; RUN: opt -S -dxil-intrinsic-expansion -scalarizer -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
|
||||
|
||||
; Make sure correct dxil expansions for atan2 are generated for float and half.
|
||||
|
||||
define noundef float @atan2_float(float noundef %y, float noundef %x) {
|
||||
entry:
|
||||
; CHECK: [[DIV:%.+]] = fdiv float %y, %x
|
||||
; EXPCHECK: [[ATAN:%.+]] = call float @llvm.atan.f32(float [[DIV]])
|
||||
; DOPCHECK: [[ATAN:%.+]] = call float @dx.op.unary.f32(i32 17, float [[DIV]])
|
||||
; CHECK-DAG: [[ADD_PI:%.+]] = fadd float [[ATAN]], 0x400921FB60000000
|
||||
; CHECK-DAG: [[SUB_PI:%.+]] = fsub float [[ATAN]], 0x400921FB60000000
|
||||
; CHECK-DAG: [[X_LT_0:%.+]] = fcmp olt float %x, 0.000000e+00
|
||||
; CHECK-DAG: [[X_EQ_0:%.+]] = fcmp oeq float %x, 0.000000e+00
|
||||
; CHECK-DAG: [[Y_GE_0:%.+]] = fcmp oge float %y, 0.000000e+00
|
||||
; CHECK-DAG: [[Y_LT_0:%.+]] = fcmp olt float %y, 0.000000e+00
|
||||
; CHECK: [[XLT0_AND_YGE0:%.+]] = and i1 [[X_LT_0]], [[Y_GE_0]]
|
||||
; CHECK: [[SELECT_ADD_PI:%.+]] = select i1 [[XLT0_AND_YGE0]], float [[ADD_PI]], float [[ATAN]]
|
||||
; CHECK: [[XLT0_AND_YLT0:%.+]] = and i1 [[X_LT_0]], [[Y_LT_0]]
|
||||
; CHECK: [[SELECT_SUB_PI:%.+]] = select i1 [[XLT0_AND_YLT0]], float [[SUB_PI]], float [[SELECT_ADD_PI]]
|
||||
; CHECK: [[XEQ0_AND_YLT0:%.+]] = and i1 [[X_EQ_0]], [[Y_LT_0]]
|
||||
; CHECK: [[SELECT_NEGHPI:%.+]] = select i1 [[XEQ0_AND_YLT0]], float 0xBFF921FB60000000, float [[SELECT_SUB_PI]]
|
||||
; CHECK: [[XEQ0_AND_YGE0:%.+]] = and i1 [[X_EQ_0]], [[Y_GE_0]]
|
||||
; CHECK: [[SELECT_HPI:%.+]] = select i1 [[XEQ0_AND_YGE0]], float 0x3FF921FB60000000, float [[SELECT_NEGHPI]]
|
||||
; CHECK: ret float [[SELECT_HPI]]
|
||||
%elt.atan2 = call float @llvm.atan2.f32(float %y, float %x)
|
||||
ret float %elt.atan2
|
||||
}
|
||||
|
||||
define noundef half @atan2_half(half noundef %y, half noundef %x) {
|
||||
entry:
|
||||
; CHECK: [[DIV:%.+]] = fdiv half %y, %x
|
||||
; EXPCHECK: [[ATAN:%.+]] = call half @llvm.atan.f16(half [[DIV]])
|
||||
; DOPCHECK: [[ATAN:%.+]] = call half @dx.op.unary.f16(i32 17, half [[DIV]])
|
||||
; CHECK-DAG: [[ADD_PI:%.+]] = fadd half [[ATAN]], 0xH4248
|
||||
; CHECK-DAG: [[SUB_PI:%.+]] = fsub half [[ATAN]], 0xH4248
|
||||
; CHECK-DAG: [[X_LT_0:%.+]] = fcmp olt half %x, 0xH0000
|
||||
; CHECK-DAG: [[X_EQ_0:%.+]] = fcmp oeq half %x, 0xH0000
|
||||
; CHECK-DAG: [[Y_GE_0:%.+]] = fcmp oge half %y, 0xH0000
|
||||
; CHECK-DAG: [[Y_LT_0:%.+]] = fcmp olt half %y, 0xH0000
|
||||
; CHECK: [[XLT0_AND_YGE0:%.+]] = and i1 [[X_LT_0]], [[Y_GE_0]]
|
||||
; CHECK: [[SELECT_ADD_PI:%.+]] = select i1 [[XLT0_AND_YGE0]], half [[ADD_PI]], half [[ATAN]]
|
||||
; CHECK: [[XLT0_AND_YLT0:%.+]] = and i1 [[X_LT_0]], [[Y_LT_0]]
|
||||
; CHECK: [[SELECT_SUB_PI:%.+]] = select i1 [[XLT0_AND_YLT0]], half [[SUB_PI]], half [[SELECT_ADD_PI]]
|
||||
; CHECK: [[XEQ0_AND_YLT0:%.+]] = and i1 [[X_EQ_0]], [[Y_LT_0]]
|
||||
; CHECK: [[SELECT_NEGHPI:%.+]] = select i1 [[XEQ0_AND_YLT0]], half 0xHBE48, half [[SELECT_SUB_PI]]
|
||||
; CHECK: [[XEQ0_AND_YGE0:%.+]] = and i1 [[X_EQ_0]], [[Y_GE_0]]
|
||||
; CHECK: [[SELECT_HPI:%.+]] = select i1 [[XEQ0_AND_YGE0]], half 0xH3E48, half [[SELECT_NEGHPI]]
|
||||
; CHECK: ret half [[SELECT_HPI]]
|
||||
%elt.atan2 = call half @llvm.atan2.f16(half %y, half %x)
|
||||
ret half %elt.atan2
|
||||
}
|
||||
|
||||
define noundef <4 x float> @atan2_float4(<4 x float> noundef %y, <4 x float> noundef %x) {
|
||||
entry:
|
||||
; Just Expansion, no scalarization or lowering:
|
||||
; EXPCHECK: [[DIV:%.+]] = fdiv <4 x float> %y, %x
|
||||
; EXPCHECK: [[ATAN:%.+]] = call <4 x float> @llvm.atan.v4f32(<4 x float> [[DIV]])
|
||||
; EXPCHECK-DAG: [[ADD_PI:%.+]] = fadd <4 x float> [[ATAN]], <float 0x400921FB60000000, float 0x400921FB60000000, float 0x400921FB60000000, float 0x400921FB60000000>
|
||||
; EXPCHECK-DAG: [[SUB_PI:%.+]] = fsub <4 x float> [[ATAN]], <float 0x400921FB60000000, float 0x400921FB60000000, float 0x400921FB60000000, float 0x400921FB60000000>
|
||||
; EXPCHECK-DAG: [[X_LT_0:%.+]] = fcmp olt <4 x float> %x, zeroinitializer
|
||||
; EXPCHECK-DAG: [[X_EQ_0:%.+]] = fcmp oeq <4 x float> %x, zeroinitializer
|
||||
; EXPCHECK-DAG: [[Y_GE_0:%.+]] = fcmp oge <4 x float> %y, zeroinitializer
|
||||
; EXPCHECK-DAG: [[Y_LT_0:%.+]] = fcmp olt <4 x float> %y, zeroinitializer
|
||||
; EXPCHECK: [[XLT0_AND_YGE0:%.+]] = and <4 x i1> [[X_LT_0]], [[Y_GE_0]]
|
||||
; EXPCHECK: [[SELECT_ADD_PI:%.+]] = select <4 x i1> [[XLT0_AND_YGE0]], <4 x float> [[ADD_PI]], <4 x float> [[ATAN]]
|
||||
; EXPCHECK: [[XLT0_AND_YLT0:%.+]] = and <4 x i1> [[X_LT_0]], [[Y_LT_0]]
|
||||
; EXPCHECK: [[SELECT_SUB_PI:%.+]] = select <4 x i1> [[XLT0_AND_YLT0]], <4 x float> [[SUB_PI]], <4 x float> [[SELECT_ADD_PI]]
|
||||
; EXPCHECK: [[XEQ0_AND_YLT0:%.+]] = and <4 x i1> [[X_EQ_0]], [[Y_LT_0]]
|
||||
; EXPCHECK: [[SELECT_NEGHPI:%.+]] = select <4 x i1> [[XEQ0_AND_YLT0]], <4 x float> <float 0xBFF921FB60000000, float 0xBFF921FB60000000, float 0xBFF921FB60000000, float 0xBFF921FB60000000>, <4 x float> [[SELECT_SUB_PI]]
|
||||
; EXPCHECK: [[XEQ0_AND_YGE0:%.+]] = and <4 x i1> [[X_EQ_0]], [[Y_GE_0]]
|
||||
; EXPCHECK: [[SELECT_HPI:%.+]] = select <4 x i1> [[XEQ0_AND_YGE0]], <4 x float> <float 0x3FF921FB60000000, float 0x3FF921FB60000000, float 0x3FF921FB60000000, float 0x3FF921FB60000000>, <4 x float> [[SELECT_NEGHPI]]
|
||||
; EXPCHECK: ret <4 x float> [[SELECT_HPI]]
|
||||
|
||||
; Scalarization occurs after expansion, so atan scalarization is tested separately.
|
||||
; Expansion, scalarization and lowering:
|
||||
; Just make sure this expands to exactly 4 scalar DXIL atan (OpCode=17) calls.
|
||||
; DOPCHECK-COUNT-4: call float @dx.op.unary.f32(i32 17, float %{{.*}})
|
||||
; DOPCHECK-NOT: call float @dx.op.unary.f32(i32 17,
|
||||
|
||||
%elt.atan2 = call <4 x float> @llvm.atan2.v4f32(<4 x float> %y, <4 x float> %x)
|
||||
ret <4 x float> %elt.atan2
|
||||
}
|
||||
|
||||
declare half @llvm.atan2.f16(half, half)
|
||||
declare float @llvm.atan2.f32(float, float)
|
||||
declare <4 x float> @llvm.atan2.v4f32(<4 x float>, <4 x float>)
|
||||
; RUN: opt -S -dxil-intrinsic-expansion -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
|
||||
; RUN: opt -S -dxil-intrinsic-expansion -scalarizer -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
|
||||
|
||||
; Make sure correct dxil expansions for atan2 are generated for float and half.
|
||||
|
||||
define noundef float @atan2_float(float noundef %y, float noundef %x) {
|
||||
entry:
|
||||
; CHECK: [[DIV:%.+]] = fdiv float %y, %x
|
||||
; EXPCHECK: [[ATAN:%.+]] = call float @llvm.atan.f32(float [[DIV]])
|
||||
; DOPCHECK: [[ATAN:%.+]] = call float @dx.op.unary.f32(i32 17, float [[DIV]])
|
||||
; CHECK-DAG: [[ADD_PI:%.+]] = fadd float [[ATAN]], 0x400921FB60000000
|
||||
; CHECK-DAG: [[SUB_PI:%.+]] = fsub float [[ATAN]], 0x400921FB60000000
|
||||
; CHECK-DAG: [[X_LT_0:%.+]] = fcmp olt float %x, 0.000000e+00
|
||||
; CHECK-DAG: [[X_EQ_0:%.+]] = fcmp oeq float %x, 0.000000e+00
|
||||
; CHECK-DAG: [[Y_GE_0:%.+]] = fcmp oge float %y, 0.000000e+00
|
||||
; CHECK-DAG: [[Y_LT_0:%.+]] = fcmp olt float %y, 0.000000e+00
|
||||
; CHECK: [[XLT0_AND_YGE0:%.+]] = and i1 [[X_LT_0]], [[Y_GE_0]]
|
||||
; CHECK: [[SELECT_ADD_PI:%.+]] = select i1 [[XLT0_AND_YGE0]], float [[ADD_PI]], float [[ATAN]]
|
||||
; CHECK: [[XLT0_AND_YLT0:%.+]] = and i1 [[X_LT_0]], [[Y_LT_0]]
|
||||
; CHECK: [[SELECT_SUB_PI:%.+]] = select i1 [[XLT0_AND_YLT0]], float [[SUB_PI]], float [[SELECT_ADD_PI]]
|
||||
; CHECK: [[XEQ0_AND_YLT0:%.+]] = and i1 [[X_EQ_0]], [[Y_LT_0]]
|
||||
; CHECK: [[SELECT_NEGHPI:%.+]] = select i1 [[XEQ0_AND_YLT0]], float 0xBFF921FB60000000, float [[SELECT_SUB_PI]]
|
||||
; CHECK: [[XEQ0_AND_YGE0:%.+]] = and i1 [[X_EQ_0]], [[Y_GE_0]]
|
||||
; CHECK: [[SELECT_HPI:%.+]] = select i1 [[XEQ0_AND_YGE0]], float 0x3FF921FB60000000, float [[SELECT_NEGHPI]]
|
||||
; CHECK: ret float [[SELECT_HPI]]
|
||||
%elt.atan2 = call float @llvm.atan2.f32(float %y, float %x)
|
||||
ret float %elt.atan2
|
||||
}
|
||||
|
||||
define noundef half @atan2_half(half noundef %y, half noundef %x) {
|
||||
entry:
|
||||
; CHECK: [[DIV:%.+]] = fdiv half %y, %x
|
||||
; EXPCHECK: [[ATAN:%.+]] = call half @llvm.atan.f16(half [[DIV]])
|
||||
; DOPCHECK: [[ATAN:%.+]] = call half @dx.op.unary.f16(i32 17, half [[DIV]])
|
||||
; CHECK-DAG: [[ADD_PI:%.+]] = fadd half [[ATAN]], 0xH4248
|
||||
; CHECK-DAG: [[SUB_PI:%.+]] = fsub half [[ATAN]], 0xH4248
|
||||
; CHECK-DAG: [[X_LT_0:%.+]] = fcmp olt half %x, 0xH0000
|
||||
; CHECK-DAG: [[X_EQ_0:%.+]] = fcmp oeq half %x, 0xH0000
|
||||
; CHECK-DAG: [[Y_GE_0:%.+]] = fcmp oge half %y, 0xH0000
|
||||
; CHECK-DAG: [[Y_LT_0:%.+]] = fcmp olt half %y, 0xH0000
|
||||
; CHECK: [[XLT0_AND_YGE0:%.+]] = and i1 [[X_LT_0]], [[Y_GE_0]]
|
||||
; CHECK: [[SELECT_ADD_PI:%.+]] = select i1 [[XLT0_AND_YGE0]], half [[ADD_PI]], half [[ATAN]]
|
||||
; CHECK: [[XLT0_AND_YLT0:%.+]] = and i1 [[X_LT_0]], [[Y_LT_0]]
|
||||
; CHECK: [[SELECT_SUB_PI:%.+]] = select i1 [[XLT0_AND_YLT0]], half [[SUB_PI]], half [[SELECT_ADD_PI]]
|
||||
; CHECK: [[XEQ0_AND_YLT0:%.+]] = and i1 [[X_EQ_0]], [[Y_LT_0]]
|
||||
; CHECK: [[SELECT_NEGHPI:%.+]] = select i1 [[XEQ0_AND_YLT0]], half 0xHBE48, half [[SELECT_SUB_PI]]
|
||||
; CHECK: [[XEQ0_AND_YGE0:%.+]] = and i1 [[X_EQ_0]], [[Y_GE_0]]
|
||||
; CHECK: [[SELECT_HPI:%.+]] = select i1 [[XEQ0_AND_YGE0]], half 0xH3E48, half [[SELECT_NEGHPI]]
|
||||
; CHECK: ret half [[SELECT_HPI]]
|
||||
%elt.atan2 = call half @llvm.atan2.f16(half %y, half %x)
|
||||
ret half %elt.atan2
|
||||
}
|
||||
|
||||
define noundef <4 x float> @atan2_float4(<4 x float> noundef %y, <4 x float> noundef %x) {
|
||||
entry:
|
||||
; Just Expansion, no scalarization or lowering:
|
||||
; EXPCHECK: [[DIV:%.+]] = fdiv <4 x float> %y, %x
|
||||
; EXPCHECK: [[ATAN:%.+]] = call <4 x float> @llvm.atan.v4f32(<4 x float> [[DIV]])
|
||||
; EXPCHECK-DAG: [[ADD_PI:%.+]] = fadd <4 x float> [[ATAN]], <float 0x400921FB60000000, float 0x400921FB60000000, float 0x400921FB60000000, float 0x400921FB60000000>
|
||||
; EXPCHECK-DAG: [[SUB_PI:%.+]] = fsub <4 x float> [[ATAN]], <float 0x400921FB60000000, float 0x400921FB60000000, float 0x400921FB60000000, float 0x400921FB60000000>
|
||||
; EXPCHECK-DAG: [[X_LT_0:%.+]] = fcmp olt <4 x float> %x, zeroinitializer
|
||||
; EXPCHECK-DAG: [[X_EQ_0:%.+]] = fcmp oeq <4 x float> %x, zeroinitializer
|
||||
; EXPCHECK-DAG: [[Y_GE_0:%.+]] = fcmp oge <4 x float> %y, zeroinitializer
|
||||
; EXPCHECK-DAG: [[Y_LT_0:%.+]] = fcmp olt <4 x float> %y, zeroinitializer
|
||||
; EXPCHECK: [[XLT0_AND_YGE0:%.+]] = and <4 x i1> [[X_LT_0]], [[Y_GE_0]]
|
||||
; EXPCHECK: [[SELECT_ADD_PI:%.+]] = select <4 x i1> [[XLT0_AND_YGE0]], <4 x float> [[ADD_PI]], <4 x float> [[ATAN]]
|
||||
; EXPCHECK: [[XLT0_AND_YLT0:%.+]] = and <4 x i1> [[X_LT_0]], [[Y_LT_0]]
|
||||
; EXPCHECK: [[SELECT_SUB_PI:%.+]] = select <4 x i1> [[XLT0_AND_YLT0]], <4 x float> [[SUB_PI]], <4 x float> [[SELECT_ADD_PI]]
|
||||
; EXPCHECK: [[XEQ0_AND_YLT0:%.+]] = and <4 x i1> [[X_EQ_0]], [[Y_LT_0]]
|
||||
; EXPCHECK: [[SELECT_NEGHPI:%.+]] = select <4 x i1> [[XEQ0_AND_YLT0]], <4 x float> <float 0xBFF921FB60000000, float 0xBFF921FB60000000, float 0xBFF921FB60000000, float 0xBFF921FB60000000>, <4 x float> [[SELECT_SUB_PI]]
|
||||
; EXPCHECK: [[XEQ0_AND_YGE0:%.+]] = and <4 x i1> [[X_EQ_0]], [[Y_GE_0]]
|
||||
; EXPCHECK: [[SELECT_HPI:%.+]] = select <4 x i1> [[XEQ0_AND_YGE0]], <4 x float> <float 0x3FF921FB60000000, float 0x3FF921FB60000000, float 0x3FF921FB60000000, float 0x3FF921FB60000000>, <4 x float> [[SELECT_NEGHPI]]
|
||||
; EXPCHECK: ret <4 x float> [[SELECT_HPI]]
|
||||
|
||||
; Scalarization occurs after expansion, so atan scalarization is tested separately.
|
||||
; Expansion, scalarization and lowering:
|
||||
; Just make sure this expands to exactly 4 scalar DXIL atan (OpCode=17) calls.
|
||||
; DOPCHECK-COUNT-4: call float @dx.op.unary.f32(i32 17, float %{{.*}})
|
||||
; DOPCHECK-NOT: call float @dx.op.unary.f32(i32 17,
|
||||
|
||||
%elt.atan2 = call <4 x float> @llvm.atan2.v4f32(<4 x float> %y, <4 x float> %x)
|
||||
ret <4 x float> %elt.atan2
|
||||
}
|
||||
|
||||
declare half @llvm.atan2.f16(half, half)
|
||||
declare float @llvm.atan2.f32(float, float)
|
||||
declare <4 x float> @llvm.atan2.v4f32(<4 x float>, <4 x float>)
|
||||
|
@ -1,11 +1,11 @@
|
||||
; RUN: not opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
|
||||
|
||||
; DXIL operation atan does not support double overload type
|
||||
; CHECK: in function atan2_double
|
||||
; CHECK-SAME: Cannot create ATan operation: Invalid overload type
|
||||
|
||||
define noundef double @atan2_double(double noundef %a, double noundef %b) #0 {
|
||||
entry:
|
||||
%1 = call double @llvm.atan2.f64(double %a, double %b)
|
||||
ret double %1
|
||||
}
|
||||
; RUN: not opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
|
||||
|
||||
; DXIL operation atan does not support double overload type
|
||||
; CHECK: in function atan2_double
|
||||
; CHECK-SAME: Cannot create ATan operation: Invalid overload type
|
||||
|
||||
define noundef double @atan2_double(double noundef %a, double noundef %b) #0 {
|
||||
entry:
|
||||
%1 = call double @llvm.atan2.f64(double %a, double %b)
|
||||
ret double %1
|
||||
}
|
||||
|
@ -1,56 +1,56 @@
|
||||
; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s
|
||||
|
||||
; Make sure dxil operation function calls for cross are generated for half/float.
|
||||
|
||||
declare <3 x half> @llvm.dx.cross.v3f16(<3 x half>, <3 x half>)
|
||||
declare <3 x float> @llvm.dx.cross.v3f32(<3 x float>, <3 x float>)
|
||||
|
||||
define noundef <3 x half> @test_cross_half3(<3 x half> noundef %p0, <3 x half> noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %x0 = extractelement <3 x half> %p0, i64 0
|
||||
; CHECK: %x1 = extractelement <3 x half> %p0, i64 1
|
||||
; CHECK: %x2 = extractelement <3 x half> %p0, i64 2
|
||||
; CHECK: %y0 = extractelement <3 x half> %p1, i64 0
|
||||
; CHECK: %y1 = extractelement <3 x half> %p1, i64 1
|
||||
; CHECK: %y2 = extractelement <3 x half> %p1, i64 2
|
||||
; CHECK: %0 = fmul half %x1, %y2
|
||||
; CHECK: %1 = fmul half %x2, %y1
|
||||
; CHECK: %hlsl.cross1 = fsub half %0, %1
|
||||
; CHECK: %2 = fmul half %x2, %y0
|
||||
; CHECK: %3 = fmul half %x0, %y2
|
||||
; CHECK: %hlsl.cross2 = fsub half %2, %3
|
||||
; CHECK: %4 = fmul half %x0, %y1
|
||||
; CHECK: %5 = fmul half %x1, %y0
|
||||
; CHECK: %hlsl.cross3 = fsub half %4, %5
|
||||
; CHECK: %6 = insertelement <3 x half> undef, half %hlsl.cross1, i64 0
|
||||
; CHECK: %7 = insertelement <3 x half> %6, half %hlsl.cross2, i64 1
|
||||
; CHECK: %8 = insertelement <3 x half> %7, half %hlsl.cross3, i64 2
|
||||
; CHECK: ret <3 x half> %8
|
||||
%hlsl.cross = call <3 x half> @llvm.dx.cross.v3f16(<3 x half> %p0, <3 x half> %p1)
|
||||
ret <3 x half> %hlsl.cross
|
||||
}
|
||||
|
||||
define noundef <3 x float> @test_cross_float3(<3 x float> noundef %p0, <3 x float> noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %x0 = extractelement <3 x float> %p0, i64 0
|
||||
; CHECK: %x1 = extractelement <3 x float> %p0, i64 1
|
||||
; CHECK: %x2 = extractelement <3 x float> %p0, i64 2
|
||||
; CHECK: %y0 = extractelement <3 x float> %p1, i64 0
|
||||
; CHECK: %y1 = extractelement <3 x float> %p1, i64 1
|
||||
; CHECK: %y2 = extractelement <3 x float> %p1, i64 2
|
||||
; CHECK: %0 = fmul float %x1, %y2
|
||||
; CHECK: %1 = fmul float %x2, %y1
|
||||
; CHECK: %hlsl.cross1 = fsub float %0, %1
|
||||
; CHECK: %2 = fmul float %x2, %y0
|
||||
; CHECK: %3 = fmul float %x0, %y2
|
||||
; CHECK: %hlsl.cross2 = fsub float %2, %3
|
||||
; CHECK: %4 = fmul float %x0, %y1
|
||||
; CHECK: %5 = fmul float %x1, %y0
|
||||
; CHECK: %hlsl.cross3 = fsub float %4, %5
|
||||
; CHECK: %6 = insertelement <3 x float> undef, float %hlsl.cross1, i64 0
|
||||
; CHECK: %7 = insertelement <3 x float> %6, float %hlsl.cross2, i64 1
|
||||
; CHECK: %8 = insertelement <3 x float> %7, float %hlsl.cross3, i64 2
|
||||
; CHECK: ret <3 x float> %8
|
||||
%hlsl.cross = call <3 x float> @llvm.dx.cross.v3f32(<3 x float> %p0, <3 x float> %p1)
|
||||
ret <3 x float> %hlsl.cross
|
||||
}
|
||||
; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s
|
||||
|
||||
; Make sure dxil operation function calls for cross are generated for half/float.
|
||||
|
||||
declare <3 x half> @llvm.dx.cross.v3f16(<3 x half>, <3 x half>)
|
||||
declare <3 x float> @llvm.dx.cross.v3f32(<3 x float>, <3 x float>)
|
||||
|
||||
define noundef <3 x half> @test_cross_half3(<3 x half> noundef %p0, <3 x half> noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %x0 = extractelement <3 x half> %p0, i64 0
|
||||
; CHECK: %x1 = extractelement <3 x half> %p0, i64 1
|
||||
; CHECK: %x2 = extractelement <3 x half> %p0, i64 2
|
||||
; CHECK: %y0 = extractelement <3 x half> %p1, i64 0
|
||||
; CHECK: %y1 = extractelement <3 x half> %p1, i64 1
|
||||
; CHECK: %y2 = extractelement <3 x half> %p1, i64 2
|
||||
; CHECK: %0 = fmul half %x1, %y2
|
||||
; CHECK: %1 = fmul half %x2, %y1
|
||||
; CHECK: %hlsl.cross1 = fsub half %0, %1
|
||||
; CHECK: %2 = fmul half %x2, %y0
|
||||
; CHECK: %3 = fmul half %x0, %y2
|
||||
; CHECK: %hlsl.cross2 = fsub half %2, %3
|
||||
; CHECK: %4 = fmul half %x0, %y1
|
||||
; CHECK: %5 = fmul half %x1, %y0
|
||||
; CHECK: %hlsl.cross3 = fsub half %4, %5
|
||||
; CHECK: %6 = insertelement <3 x half> undef, half %hlsl.cross1, i64 0
|
||||
; CHECK: %7 = insertelement <3 x half> %6, half %hlsl.cross2, i64 1
|
||||
; CHECK: %8 = insertelement <3 x half> %7, half %hlsl.cross3, i64 2
|
||||
; CHECK: ret <3 x half> %8
|
||||
%hlsl.cross = call <3 x half> @llvm.dx.cross.v3f16(<3 x half> %p0, <3 x half> %p1)
|
||||
ret <3 x half> %hlsl.cross
|
||||
}
|
||||
|
||||
define noundef <3 x float> @test_cross_float3(<3 x float> noundef %p0, <3 x float> noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %x0 = extractelement <3 x float> %p0, i64 0
|
||||
; CHECK: %x1 = extractelement <3 x float> %p0, i64 1
|
||||
; CHECK: %x2 = extractelement <3 x float> %p0, i64 2
|
||||
; CHECK: %y0 = extractelement <3 x float> %p1, i64 0
|
||||
; CHECK: %y1 = extractelement <3 x float> %p1, i64 1
|
||||
; CHECK: %y2 = extractelement <3 x float> %p1, i64 2
|
||||
; CHECK: %0 = fmul float %x1, %y2
|
||||
; CHECK: %1 = fmul float %x2, %y1
|
||||
; CHECK: %hlsl.cross1 = fsub float %0, %1
|
||||
; CHECK: %2 = fmul float %x2, %y0
|
||||
; CHECK: %3 = fmul float %x0, %y2
|
||||
; CHECK: %hlsl.cross2 = fsub float %2, %3
|
||||
; CHECK: %4 = fmul float %x0, %y1
|
||||
; CHECK: %5 = fmul float %x1, %y0
|
||||
; CHECK: %hlsl.cross3 = fsub float %4, %5
|
||||
; CHECK: %6 = insertelement <3 x float> undef, float %hlsl.cross1, i64 0
|
||||
; CHECK: %7 = insertelement <3 x float> %6, float %hlsl.cross2, i64 1
|
||||
; CHECK: %8 = insertelement <3 x float> %7, float %hlsl.cross3, i64 2
|
||||
; CHECK: ret <3 x float> %8
|
||||
%hlsl.cross = call <3 x float> @llvm.dx.cross.v3f32(<3 x float> %p0, <3 x float> %p1)
|
||||
ret <3 x float> %hlsl.cross
|
||||
}
|
||||
|
@ -1,112 +1,112 @@
|
||||
; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
|
||||
; RUN: opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
|
||||
|
||||
; Make sure dxil operation function calls for normalize are generated for half/float.
|
||||
|
||||
declare half @llvm.dx.normalize.f16(half)
|
||||
declare <2 x half> @llvm.dx.normalize.v2f16(<2 x half>)
|
||||
declare <3 x half> @llvm.dx.normalize.v3f16(<3 x half>)
|
||||
declare <4 x half> @llvm.dx.normalize.v4f16(<4 x half>)
|
||||
|
||||
declare float @llvm.dx.normalize.f32(float)
|
||||
declare <2 x float> @llvm.dx.normalize.v2f32(<2 x float>)
|
||||
declare <3 x float> @llvm.dx.normalize.v3f32(<3 x float>)
|
||||
declare <4 x float> @llvm.dx.normalize.v4f32(<4 x float>)
|
||||
|
||||
define noundef half @test_normalize_half(half noundef %p0) {
|
||||
entry:
|
||||
; CHECK: fdiv half %p0, %p0
|
||||
%hlsl.normalize = call half @llvm.dx.normalize.f16(half %p0)
|
||||
ret half %hlsl.normalize
|
||||
}
|
||||
|
||||
define noundef <2 x half> @test_normalize_half2(<2 x half> noundef %p0) {
|
||||
entry:
|
||||
; EXPCHECK: [[doth2:%.*]] = call half @llvm.dx.dot2.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}})
|
||||
; DOPCHECK: [[doth2:%.*]] = call half @dx.op.dot2.f16(i32 54, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}})
|
||||
; EXPCHECK: [[rsqrt:%.*]] = call half @llvm.dx.rsqrt.f16(half [[doth2]])
|
||||
; DOPCHECK: [[rsqrt:%.*]] = call half @dx.op.unary.f16(i32 25, half [[doth2]])
|
||||
; CHECK: [[splatinserth2:%.*]] = insertelement <2 x half> poison, half [[rsqrt]], i64 0
|
||||
; CHECK: [[splat:%.*]] = shufflevector <2 x half> [[splatinserth2]], <2 x half> poison, <2 x i32> zeroinitializer
|
||||
; CHECK: fmul <2 x half> %p0, [[splat]]
|
||||
|
||||
%hlsl.normalize = call <2 x half> @llvm.dx.normalize.v2f16(<2 x half> %p0)
|
||||
ret <2 x half> %hlsl.normalize
|
||||
}
|
||||
|
||||
define noundef <3 x half> @test_normalize_half3(<3 x half> noundef %p0) {
|
||||
entry:
|
||||
; EXPCHECK: [[doth3:%.*]] = call half @llvm.dx.dot3.v3f16(<3 x half> %{{.*}}, <3 x half> %{{.*}})
|
||||
; DOPCHECK: [[doth3:%.*]] = call half @dx.op.dot3.f16(i32 55, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}})
|
||||
; EXPCHECK: [[rsqrt:%.*]] = call half @llvm.dx.rsqrt.f16(half [[doth3]])
|
||||
; DOPCHECK: [[rsqrt:%.*]] = call half @dx.op.unary.f16(i32 25, half [[doth3]])
|
||||
; CHECK: [[splatinserth3:%.*]] = insertelement <3 x half> poison, half [[rsqrt]], i64 0
|
||||
; CHECK: [[splat:%.*]] shufflevector <3 x half> [[splatinserth3]], <3 x half> poison, <3 x i32> zeroinitializer
|
||||
; CHECK: fmul <3 x half> %p0, %.splat
|
||||
|
||||
%hlsl.normalize = call <3 x half> @llvm.dx.normalize.v3f16(<3 x half> %p0)
|
||||
ret <3 x half> %hlsl.normalize
|
||||
}
|
||||
|
||||
define noundef <4 x half> @test_normalize_half4(<4 x half> noundef %p0) {
|
||||
entry:
|
||||
; EXPCHECK: [[doth4:%.*]] = call half @llvm.dx.dot4.v4f16(<4 x half> %{{.*}}, <4 x half> %{{.*}})
|
||||
; DOPCHECK: [[doth4:%.*]] = call half @dx.op.dot4.f16(i32 56, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}})
|
||||
; EXPCHECK: [[rsqrt:%.*]] = call half @llvm.dx.rsqrt.f16(half [[doth4]])
|
||||
; DOPCHECK: [[rsqrt:%.*]] = call half @dx.op.unary.f16(i32 25, half [[doth4]])
|
||||
; CHECK: [[splatinserth4:%.*]] = insertelement <4 x half> poison, half [[rsqrt]], i64 0
|
||||
; CHECK: [[splat:%.*]] shufflevector <4 x half> [[splatinserth4]], <4 x half> poison, <4 x i32> zeroinitializer
|
||||
; CHECK: fmul <4 x half> %p0, %.splat
|
||||
|
||||
%hlsl.normalize = call <4 x half> @llvm.dx.normalize.v4f16(<4 x half> %p0)
|
||||
ret <4 x half> %hlsl.normalize
|
||||
}
|
||||
|
||||
define noundef float @test_normalize_float(float noundef %p0) {
|
||||
entry:
|
||||
; CHECK: fdiv float %p0, %p0
|
||||
%hlsl.normalize = call float @llvm.dx.normalize.f32(float %p0)
|
||||
ret float %hlsl.normalize
|
||||
}
|
||||
|
||||
define noundef <2 x float> @test_normalize_float2(<2 x float> noundef %p0) {
|
||||
entry:
|
||||
; EXPCHECK: [[dotf2:%.*]] = call float @llvm.dx.dot2.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}})
|
||||
; DOPCHECK: [[dotf2:%.*]] = call float @dx.op.dot2.f32(i32 54, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}})
|
||||
; EXPCHECK: [[rsqrt:%.*]] = call float @llvm.dx.rsqrt.f32(float [[dotf2]])
|
||||
; DOPCHECK: [[rsqrt:%.*]] = call float @dx.op.unary.f32(i32 25, float [[dotf2]])
|
||||
; CHECK: [[splatinsertf2:%.*]] = insertelement <2 x float> poison, float [[rsqrt]], i64 0
|
||||
; CHECK: [[splat:%.*]] shufflevector <2 x float> [[splatinsertf2]], <2 x float> poison, <2 x i32> zeroinitializer
|
||||
; CHECK: fmul <2 x float> %p0, %.splat
|
||||
|
||||
%hlsl.normalize = call <2 x float> @llvm.dx.normalize.v2f32(<2 x float> %p0)
|
||||
ret <2 x float> %hlsl.normalize
|
||||
}
|
||||
|
||||
define noundef <3 x float> @test_normalize_float3(<3 x float> noundef %p0) {
|
||||
entry:
|
||||
; EXPCHECK: [[dotf3:%.*]] = call float @llvm.dx.dot3.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}})
|
||||
; DOPCHECK: [[dotf3:%.*]] = call float @dx.op.dot3.f32(i32 55, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}})
|
||||
; EXPCHECK: [[rsqrt:%.*]] = call float @llvm.dx.rsqrt.f32(float [[dotf3]])
|
||||
; DOPCHECK: [[rsqrt:%.*]] = call float @dx.op.unary.f32(i32 25, float [[dotf3]])
|
||||
; CHECK: [[splatinsertf3:%.*]] = insertelement <3 x float> poison, float [[rsqrt]], i64 0
|
||||
; CHECK: [[splat:%.*]] shufflevector <3 x float> [[splatinsertf3]], <3 x float> poison, <3 x i32> zeroinitializer
|
||||
; CHECK: fmul <3 x float> %p0, %.splat
|
||||
|
||||
%hlsl.normalize = call <3 x float> @llvm.dx.normalize.v3f32(<3 x float> %p0)
|
||||
ret <3 x float> %hlsl.normalize
|
||||
}
|
||||
|
||||
define noundef <4 x float> @test_normalize_float4(<4 x float> noundef %p0) {
|
||||
entry:
|
||||
; EXPCHECK: [[dotf4:%.*]] = call float @llvm.dx.dot4.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
|
||||
; DOPCHECK: [[dotf4:%.*]] = call float @dx.op.dot4.f32(i32 56, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}})
|
||||
; EXPCHECK: [[rsqrt:%.*]] = call float @llvm.dx.rsqrt.f32(float [[dotf4]])
|
||||
; DOPCHECK: [[rsqrt:%.*]] = call float @dx.op.unary.f32(i32 25, float [[dotf4]])
|
||||
; CHECK: [[splatinsertf4:%.*]] = insertelement <4 x float> poison, float [[rsqrt]], i64 0
|
||||
; CHECK: [[splat:%.*]] shufflevector <4 x float> [[splatinsertf4]], <4 x float> poison, <4 x i32> zeroinitializer
|
||||
; CHECK: fmul <4 x float> %p0, %.splat
|
||||
|
||||
%hlsl.normalize = call <4 x float> @llvm.dx.normalize.v4f32(<4 x float> %p0)
|
||||
ret <4 x float> %hlsl.normalize
|
||||
}
|
||||
; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK
|
||||
; RUN: opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK
|
||||
|
||||
; Make sure dxil operation function calls for normalize are generated for half/float.
|
||||
|
||||
declare half @llvm.dx.normalize.f16(half)
|
||||
declare <2 x half> @llvm.dx.normalize.v2f16(<2 x half>)
|
||||
declare <3 x half> @llvm.dx.normalize.v3f16(<3 x half>)
|
||||
declare <4 x half> @llvm.dx.normalize.v4f16(<4 x half>)
|
||||
|
||||
declare float @llvm.dx.normalize.f32(float)
|
||||
declare <2 x float> @llvm.dx.normalize.v2f32(<2 x float>)
|
||||
declare <3 x float> @llvm.dx.normalize.v3f32(<3 x float>)
|
||||
declare <4 x float> @llvm.dx.normalize.v4f32(<4 x float>)
|
||||
|
||||
define noundef half @test_normalize_half(half noundef %p0) {
|
||||
entry:
|
||||
; CHECK: fdiv half %p0, %p0
|
||||
%hlsl.normalize = call half @llvm.dx.normalize.f16(half %p0)
|
||||
ret half %hlsl.normalize
|
||||
}
|
||||
|
||||
define noundef <2 x half> @test_normalize_half2(<2 x half> noundef %p0) {
|
||||
entry:
|
||||
; EXPCHECK: [[doth2:%.*]] = call half @llvm.dx.dot2.v2f16(<2 x half> %{{.*}}, <2 x half> %{{.*}})
|
||||
; DOPCHECK: [[doth2:%.*]] = call half @dx.op.dot2.f16(i32 54, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}})
|
||||
; EXPCHECK: [[rsqrt:%.*]] = call half @llvm.dx.rsqrt.f16(half [[doth2]])
|
||||
; DOPCHECK: [[rsqrt:%.*]] = call half @dx.op.unary.f16(i32 25, half [[doth2]])
|
||||
; CHECK: [[splatinserth2:%.*]] = insertelement <2 x half> poison, half [[rsqrt]], i64 0
|
||||
; CHECK: [[splat:%.*]] = shufflevector <2 x half> [[splatinserth2]], <2 x half> poison, <2 x i32> zeroinitializer
|
||||
; CHECK: fmul <2 x half> %p0, [[splat]]
|
||||
|
||||
%hlsl.normalize = call <2 x half> @llvm.dx.normalize.v2f16(<2 x half> %p0)
|
||||
ret <2 x half> %hlsl.normalize
|
||||
}
|
||||
|
||||
define noundef <3 x half> @test_normalize_half3(<3 x half> noundef %p0) {
|
||||
entry:
|
||||
; EXPCHECK: [[doth3:%.*]] = call half @llvm.dx.dot3.v3f16(<3 x half> %{{.*}}, <3 x half> %{{.*}})
|
||||
; DOPCHECK: [[doth3:%.*]] = call half @dx.op.dot3.f16(i32 55, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}})
|
||||
; EXPCHECK: [[rsqrt:%.*]] = call half @llvm.dx.rsqrt.f16(half [[doth3]])
|
||||
; DOPCHECK: [[rsqrt:%.*]] = call half @dx.op.unary.f16(i32 25, half [[doth3]])
|
||||
; CHECK: [[splatinserth3:%.*]] = insertelement <3 x half> poison, half [[rsqrt]], i64 0
|
||||
; CHECK: [[splat:%.*]] shufflevector <3 x half> [[splatinserth3]], <3 x half> poison, <3 x i32> zeroinitializer
|
||||
; CHECK: fmul <3 x half> %p0, %.splat
|
||||
|
||||
%hlsl.normalize = call <3 x half> @llvm.dx.normalize.v3f16(<3 x half> %p0)
|
||||
ret <3 x half> %hlsl.normalize
|
||||
}
|
||||
|
||||
define noundef <4 x half> @test_normalize_half4(<4 x half> noundef %p0) {
|
||||
entry:
|
||||
; EXPCHECK: [[doth4:%.*]] = call half @llvm.dx.dot4.v4f16(<4 x half> %{{.*}}, <4 x half> %{{.*}})
|
||||
; DOPCHECK: [[doth4:%.*]] = call half @dx.op.dot4.f16(i32 56, half %{{.*}}, half %{{.*}}, half %{{.*}}, half %{{.*}})
|
||||
; EXPCHECK: [[rsqrt:%.*]] = call half @llvm.dx.rsqrt.f16(half [[doth4]])
|
||||
; DOPCHECK: [[rsqrt:%.*]] = call half @dx.op.unary.f16(i32 25, half [[doth4]])
|
||||
; CHECK: [[splatinserth4:%.*]] = insertelement <4 x half> poison, half [[rsqrt]], i64 0
|
||||
; CHECK: [[splat:%.*]] shufflevector <4 x half> [[splatinserth4]], <4 x half> poison, <4 x i32> zeroinitializer
|
||||
; CHECK: fmul <4 x half> %p0, %.splat
|
||||
|
||||
%hlsl.normalize = call <4 x half> @llvm.dx.normalize.v4f16(<4 x half> %p0)
|
||||
ret <4 x half> %hlsl.normalize
|
||||
}
|
||||
|
||||
define noundef float @test_normalize_float(float noundef %p0) {
|
||||
entry:
|
||||
; CHECK: fdiv float %p0, %p0
|
||||
%hlsl.normalize = call float @llvm.dx.normalize.f32(float %p0)
|
||||
ret float %hlsl.normalize
|
||||
}
|
||||
|
||||
define noundef <2 x float> @test_normalize_float2(<2 x float> noundef %p0) {
|
||||
entry:
|
||||
; EXPCHECK: [[dotf2:%.*]] = call float @llvm.dx.dot2.v2f32(<2 x float> %{{.*}}, <2 x float> %{{.*}})
|
||||
; DOPCHECK: [[dotf2:%.*]] = call float @dx.op.dot2.f32(i32 54, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}})
|
||||
; EXPCHECK: [[rsqrt:%.*]] = call float @llvm.dx.rsqrt.f32(float [[dotf2]])
|
||||
; DOPCHECK: [[rsqrt:%.*]] = call float @dx.op.unary.f32(i32 25, float [[dotf2]])
|
||||
; CHECK: [[splatinsertf2:%.*]] = insertelement <2 x float> poison, float [[rsqrt]], i64 0
|
||||
; CHECK: [[splat:%.*]] shufflevector <2 x float> [[splatinsertf2]], <2 x float> poison, <2 x i32> zeroinitializer
|
||||
; CHECK: fmul <2 x float> %p0, %.splat
|
||||
|
||||
%hlsl.normalize = call <2 x float> @llvm.dx.normalize.v2f32(<2 x float> %p0)
|
||||
ret <2 x float> %hlsl.normalize
|
||||
}
|
||||
|
||||
define noundef <3 x float> @test_normalize_float3(<3 x float> noundef %p0) {
|
||||
entry:
|
||||
; EXPCHECK: [[dotf3:%.*]] = call float @llvm.dx.dot3.v3f32(<3 x float> %{{.*}}, <3 x float> %{{.*}})
|
||||
; DOPCHECK: [[dotf3:%.*]] = call float @dx.op.dot3.f32(i32 55, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}})
|
||||
; EXPCHECK: [[rsqrt:%.*]] = call float @llvm.dx.rsqrt.f32(float [[dotf3]])
|
||||
; DOPCHECK: [[rsqrt:%.*]] = call float @dx.op.unary.f32(i32 25, float [[dotf3]])
|
||||
; CHECK: [[splatinsertf3:%.*]] = insertelement <3 x float> poison, float [[rsqrt]], i64 0
|
||||
; CHECK: [[splat:%.*]] shufflevector <3 x float> [[splatinsertf3]], <3 x float> poison, <3 x i32> zeroinitializer
|
||||
; CHECK: fmul <3 x float> %p0, %.splat
|
||||
|
||||
%hlsl.normalize = call <3 x float> @llvm.dx.normalize.v3f32(<3 x float> %p0)
|
||||
ret <3 x float> %hlsl.normalize
|
||||
}
|
||||
|
||||
define noundef <4 x float> @test_normalize_float4(<4 x float> noundef %p0) {
|
||||
entry:
|
||||
; EXPCHECK: [[dotf4:%.*]] = call float @llvm.dx.dot4.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}})
|
||||
; DOPCHECK: [[dotf4:%.*]] = call float @dx.op.dot4.f32(i32 56, float %{{.*}}, float %{{.*}}, float %{{.*}}, float %{{.*}})
|
||||
; EXPCHECK: [[rsqrt:%.*]] = call float @llvm.dx.rsqrt.f32(float [[dotf4]])
|
||||
; DOPCHECK: [[rsqrt:%.*]] = call float @dx.op.unary.f32(i32 25, float [[dotf4]])
|
||||
; CHECK: [[splatinsertf4:%.*]] = insertelement <4 x float> poison, float [[rsqrt]], i64 0
|
||||
; CHECK: [[splat:%.*]] shufflevector <4 x float> [[splatinsertf4]], <4 x float> poison, <4 x i32> zeroinitializer
|
||||
; CHECK: fmul <4 x float> %p0, %.splat
|
||||
|
||||
%hlsl.normalize = call <4 x float> @llvm.dx.normalize.v4f32(<4 x float> %p0)
|
||||
ret <4 x float> %hlsl.normalize
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
; RUN: not opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
|
||||
|
||||
; DXIL operation normalize does not support double overload type
|
||||
; CHECK: Cannot create Dot2 operation: Invalid overload type
|
||||
|
||||
define noundef <2 x double> @test_normalize_double2(<2 x double> noundef %p0) {
|
||||
entry:
|
||||
%hlsl.normalize = call <2 x double> @llvm.dx.normalize.v2f32(<2 x double> %p0)
|
||||
ret <2 x double> %hlsl.normalize
|
||||
}
|
||||
; RUN: not opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s 2>&1 | FileCheck %s
|
||||
|
||||
; DXIL operation normalize does not support double overload type
|
||||
; CHECK: Cannot create Dot2 operation: Invalid overload type
|
||||
|
||||
define noundef <2 x double> @test_normalize_double2(<2 x double> noundef %p0) {
|
||||
entry:
|
||||
%hlsl.normalize = call <2 x double> @llvm.dx.normalize.v2f32(<2 x double> %p0)
|
||||
ret <2 x double> %hlsl.normalize
|
||||
}
|
||||
|
@ -1,78 +1,78 @@
|
||||
; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefix=CHECK
|
||||
; RUN: opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library < %s | FileCheck %s --check-prefix=CHECK
|
||||
|
||||
; Make sure dxil operation function calls for step are generated for half/float.
|
||||
|
||||
declare half @llvm.dx.step.f16(half, half)
|
||||
declare <2 x half> @llvm.dx.step.v2f16(<2 x half>, <2 x half>)
|
||||
declare <3 x half> @llvm.dx.step.v3f16(<3 x half>, <3 x half>)
|
||||
declare <4 x half> @llvm.dx.step.v4f16(<4 x half>, <4 x half>)
|
||||
|
||||
declare float @llvm.dx.step.f32(float, float)
|
||||
declare <2 x float> @llvm.dx.step.v2f32(<2 x float>, <2 x float>)
|
||||
declare <3 x float> @llvm.dx.step.v3f32(<3 x float>, <3 x float>)
|
||||
declare <4 x float> @llvm.dx.step.v4f32(<4 x float>, <4 x float>)
|
||||
|
||||
define noundef half @test_step_half(half noundef %p0, half noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %0 = fcmp olt half %p1, %p0
|
||||
; CHECK: %1 = select i1 %0, half 0xH0000, half 0xH3C00
|
||||
%hlsl.step = call half @llvm.dx.step.f16(half %p0, half %p1)
|
||||
ret half %hlsl.step
|
||||
}
|
||||
|
||||
define noundef <2 x half> @test_step_half2(<2 x half> noundef %p0, <2 x half> noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %0 = fcmp olt <2 x half> %p1, %p0
|
||||
; CHECK: %1 = select <2 x i1> %0, <2 x half> zeroinitializer, <2 x half> <half 0xH3C00, half 0xH3C00>
|
||||
%hlsl.step = call <2 x half> @llvm.dx.step.v2f16(<2 x half> %p0, <2 x half> %p1)
|
||||
ret <2 x half> %hlsl.step
|
||||
}
|
||||
|
||||
define noundef <3 x half> @test_step_half3(<3 x half> noundef %p0, <3 x half> noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %0 = fcmp olt <3 x half> %p1, %p0
|
||||
; CHECK: %1 = select <3 x i1> %0, <3 x half> zeroinitializer, <3 x half> <half 0xH3C00, half 0xH3C00, half 0xH3C00>
|
||||
%hlsl.step = call <3 x half> @llvm.dx.step.v3f16(<3 x half> %p0, <3 x half> %p1)
|
||||
ret <3 x half> %hlsl.step
|
||||
}
|
||||
|
||||
define noundef <4 x half> @test_step_half4(<4 x half> noundef %p0, <4 x half> noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %0 = fcmp olt <4 x half> %p1, %p0
|
||||
; CHECK: %1 = select <4 x i1> %0, <4 x half> zeroinitializer, <4 x half> <half 0xH3C00, half 0xH3C00, half 0xH3C00, half 0xH3C00>
|
||||
%hlsl.step = call <4 x half> @llvm.dx.step.v4f16(<4 x half> %p0, <4 x half> %p1)
|
||||
ret <4 x half> %hlsl.step
|
||||
}
|
||||
|
||||
define noundef float @test_step_float(float noundef %p0, float noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %0 = fcmp olt float %p1, %p0
|
||||
; CHECK: %1 = select i1 %0, float 0.000000e+00, float 1.000000e+00
|
||||
%hlsl.step = call float @llvm.dx.step.f32(float %p0, float %p1)
|
||||
ret float %hlsl.step
|
||||
}
|
||||
|
||||
define noundef <2 x float> @test_step_float2(<2 x float> noundef %p0, <2 x float> noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %0 = fcmp olt <2 x float> %p1, %p0
|
||||
; CHECK: %1 = select <2 x i1> %0, <2 x float> zeroinitializer, <2 x float> <float 1.000000e+00, float 1.000000e+00>
|
||||
%hlsl.step = call <2 x float> @llvm.dx.step.v2f32(<2 x float> %p0, <2 x float> %p1)
|
||||
ret <2 x float> %hlsl.step
|
||||
}
|
||||
|
||||
define noundef <3 x float> @test_step_float3(<3 x float> noundef %p0, <3 x float> noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %0 = fcmp olt <3 x float> %p1, %p0
|
||||
; CHECK: %1 = select <3 x i1> %0, <3 x float> zeroinitializer, <3 x float> <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>
|
||||
%hlsl.step = call <3 x float> @llvm.dx.step.v3f32(<3 x float> %p0, <3 x float> %p1)
|
||||
ret <3 x float> %hlsl.step
|
||||
}
|
||||
|
||||
define noundef <4 x float> @test_step_float4(<4 x float> noundef %p0, <4 x float> noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %0 = fcmp olt <4 x float> %p1, %p0
|
||||
; CHECK: %1 = select <4 x i1> %0, <4 x float> zeroinitializer, <4 x float> <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>
|
||||
%hlsl.step = call <4 x float> @llvm.dx.step.v4f32(<4 x float> %p0, <4 x float> %p1)
|
||||
ret <4 x float> %hlsl.step
|
||||
}
|
||||
; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefix=CHECK
|
||||
; RUN: opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library < %s | FileCheck %s --check-prefix=CHECK
|
||||
|
||||
; Make sure dxil operation function calls for step are generated for half/float.
|
||||
|
||||
declare half @llvm.dx.step.f16(half, half)
|
||||
declare <2 x half> @llvm.dx.step.v2f16(<2 x half>, <2 x half>)
|
||||
declare <3 x half> @llvm.dx.step.v3f16(<3 x half>, <3 x half>)
|
||||
declare <4 x half> @llvm.dx.step.v4f16(<4 x half>, <4 x half>)
|
||||
|
||||
declare float @llvm.dx.step.f32(float, float)
|
||||
declare <2 x float> @llvm.dx.step.v2f32(<2 x float>, <2 x float>)
|
||||
declare <3 x float> @llvm.dx.step.v3f32(<3 x float>, <3 x float>)
|
||||
declare <4 x float> @llvm.dx.step.v4f32(<4 x float>, <4 x float>)
|
||||
|
||||
define noundef half @test_step_half(half noundef %p0, half noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %0 = fcmp olt half %p1, %p0
|
||||
; CHECK: %1 = select i1 %0, half 0xH0000, half 0xH3C00
|
||||
%hlsl.step = call half @llvm.dx.step.f16(half %p0, half %p1)
|
||||
ret half %hlsl.step
|
||||
}
|
||||
|
||||
define noundef <2 x half> @test_step_half2(<2 x half> noundef %p0, <2 x half> noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %0 = fcmp olt <2 x half> %p1, %p0
|
||||
; CHECK: %1 = select <2 x i1> %0, <2 x half> zeroinitializer, <2 x half> <half 0xH3C00, half 0xH3C00>
|
||||
%hlsl.step = call <2 x half> @llvm.dx.step.v2f16(<2 x half> %p0, <2 x half> %p1)
|
||||
ret <2 x half> %hlsl.step
|
||||
}
|
||||
|
||||
define noundef <3 x half> @test_step_half3(<3 x half> noundef %p0, <3 x half> noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %0 = fcmp olt <3 x half> %p1, %p0
|
||||
; CHECK: %1 = select <3 x i1> %0, <3 x half> zeroinitializer, <3 x half> <half 0xH3C00, half 0xH3C00, half 0xH3C00>
|
||||
%hlsl.step = call <3 x half> @llvm.dx.step.v3f16(<3 x half> %p0, <3 x half> %p1)
|
||||
ret <3 x half> %hlsl.step
|
||||
}
|
||||
|
||||
define noundef <4 x half> @test_step_half4(<4 x half> noundef %p0, <4 x half> noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %0 = fcmp olt <4 x half> %p1, %p0
|
||||
; CHECK: %1 = select <4 x i1> %0, <4 x half> zeroinitializer, <4 x half> <half 0xH3C00, half 0xH3C00, half 0xH3C00, half 0xH3C00>
|
||||
%hlsl.step = call <4 x half> @llvm.dx.step.v4f16(<4 x half> %p0, <4 x half> %p1)
|
||||
ret <4 x half> %hlsl.step
|
||||
}
|
||||
|
||||
define noundef float @test_step_float(float noundef %p0, float noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %0 = fcmp olt float %p1, %p0
|
||||
; CHECK: %1 = select i1 %0, float 0.000000e+00, float 1.000000e+00
|
||||
%hlsl.step = call float @llvm.dx.step.f32(float %p0, float %p1)
|
||||
ret float %hlsl.step
|
||||
}
|
||||
|
||||
define noundef <2 x float> @test_step_float2(<2 x float> noundef %p0, <2 x float> noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %0 = fcmp olt <2 x float> %p1, %p0
|
||||
; CHECK: %1 = select <2 x i1> %0, <2 x float> zeroinitializer, <2 x float> <float 1.000000e+00, float 1.000000e+00>
|
||||
%hlsl.step = call <2 x float> @llvm.dx.step.v2f32(<2 x float> %p0, <2 x float> %p1)
|
||||
ret <2 x float> %hlsl.step
|
||||
}
|
||||
|
||||
define noundef <3 x float> @test_step_float3(<3 x float> noundef %p0, <3 x float> noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %0 = fcmp olt <3 x float> %p1, %p0
|
||||
; CHECK: %1 = select <3 x i1> %0, <3 x float> zeroinitializer, <3 x float> <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>
|
||||
%hlsl.step = call <3 x float> @llvm.dx.step.v3f32(<3 x float> %p0, <3 x float> %p1)
|
||||
ret <3 x float> %hlsl.step
|
||||
}
|
||||
|
||||
define noundef <4 x float> @test_step_float4(<4 x float> noundef %p0, <4 x float> noundef %p1) {
|
||||
entry:
|
||||
; CHECK: %0 = fcmp olt <4 x float> %p1, %p0
|
||||
; CHECK: %1 = select <4 x i1> %0, <4 x float> zeroinitializer, <4 x float> <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>
|
||||
%hlsl.step = call <4 x float> @llvm.dx.step.v4f32(<4 x float> %p0, <4 x float> %p1)
|
||||
ret <4 x float> %hlsl.step
|
||||
}
|
||||
|
@ -1,49 +1,49 @@
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
|
||||
; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
|
||||
; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16
|
||||
; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4
|
||||
; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4
|
||||
|
||||
define noundef float @atan2_float(float noundef %a, float noundef %b) {
|
||||
entry:
|
||||
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
|
||||
; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]]
|
||||
; CHECK: %[[#]] = OpExtInst %[[#float_32]] %[[#op_ext_glsl]] Atan2 %[[#arg0]] %[[#arg1]]
|
||||
%elt.atan2 = call float @llvm.atan2.f32(float %a, float %b)
|
||||
ret float %elt.atan2
|
||||
}
|
||||
|
||||
define noundef half @atan2_half(half noundef %a, half noundef %b) {
|
||||
entry:
|
||||
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
|
||||
; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]]
|
||||
; CHECK: %[[#]] = OpExtInst %[[#float_16]] %[[#op_ext_glsl]] Atan2 %[[#arg0]] %[[#arg1]]
|
||||
%elt.atan2 = call half @llvm.atan2.f16(half %a, half %b)
|
||||
ret half %elt.atan2
|
||||
}
|
||||
|
||||
define noundef <4 x float> @atan2_float4(<4 x float> noundef %a, <4 x float> noundef %b) {
|
||||
entry:
|
||||
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
|
||||
; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]]
|
||||
; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]] Atan2 %[[#arg0]] %[[#arg1]]
|
||||
%elt.atan2 = call <4 x float> @llvm.atan2.v4f32(<4 x float> %a, <4 x float> %b)
|
||||
ret <4 x float> %elt.atan2
|
||||
}
|
||||
|
||||
define noundef <4 x half> @atan2_half4(<4 x half> noundef %a, <4 x half> noundef %b) {
|
||||
entry:
|
||||
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
|
||||
; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]]
|
||||
; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]] Atan2 %[[#arg0]] %[[#arg1]]
|
||||
%elt.atan2 = call <4 x half> @llvm.atan2.v4f16(<4 x half> %a, <4 x half> %b)
|
||||
ret <4 x half> %elt.atan2
|
||||
}
|
||||
|
||||
declare half @llvm.atan2.f16(half, half)
|
||||
declare float @llvm.atan2.f32(float, float)
|
||||
declare <4 x half> @llvm.atan2.v4f16(<4 x half>, <4 x half>)
|
||||
declare <4 x float> @llvm.atan2.v4f32(<4 x float>, <4 x float>)
|
||||
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
|
||||
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
|
||||
|
||||
; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
|
||||
; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
|
||||
; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16
|
||||
; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4
|
||||
; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4
|
||||
|
||||
define noundef float @atan2_float(float noundef %a, float noundef %b) {
|
||||
entry:
|
||||
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
|
||||
; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]]
|
||||
; CHECK: %[[#]] = OpExtInst %[[#float_32]] %[[#op_ext_glsl]] Atan2 %[[#arg0]] %[[#arg1]]
|
||||
%elt.atan2 = call float @llvm.atan2.f32(float %a, float %b)
|
||||
ret float %elt.atan2
|
||||
}
|
||||
|
||||
define noundef half @atan2_half(half noundef %a, half noundef %b) {
|
||||
entry:
|
||||
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
|
||||
; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]]
|
||||
; CHECK: %[[#]] = OpExtInst %[[#float_16]] %[[#op_ext_glsl]] Atan2 %[[#arg0]] %[[#arg1]]
|
||||
%elt.atan2 = call half @llvm.atan2.f16(half %a, half %b)
|
||||
ret half %elt.atan2
|
||||
}
|
||||
|
||||
define noundef <4 x float> @atan2_float4(<4 x float> noundef %a, <4 x float> noundef %b) {
|
||||
entry:
|
||||
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
|
||||
; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]]
|
||||
; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]] Atan2 %[[#arg0]] %[[#arg1]]
|
||||
%elt.atan2 = call <4 x float> @llvm.atan2.v4f32(<4 x float> %a, <4 x float> %b)
|
||||
ret <4 x float> %elt.atan2
|
||||
}
|
||||
|
||||
define noundef <4 x half> @atan2_half4(<4 x half> noundef %a, <4 x half> noundef %b) {
|
||||
entry:
|
||||
; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#]]
|
||||
; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#]]
|
||||
; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]] Atan2 %[[#arg0]] %[[#arg1]]
|
||||
%elt.atan2 = call <4 x half> @llvm.atan2.v4f16(<4 x half> %a, <4 x half> %b)
|
||||
ret <4 x half> %elt.atan2
|
||||
}
|
||||
|
||||
declare half @llvm.atan2.f16(half, half)
|
||||
declare float @llvm.atan2.f32(float, float)
|
||||
declare <4 x half> @llvm.atan2.v4f16(<4 x half>, <4 x half>)
|
||||
declare <4 x float> @llvm.atan2.v4f32(<4 x float>, <4 x float>)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user