diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll index 1b63322610a1..008637812573 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll @@ -54,6 +54,8 @@ private predicate isDeeplyConstBelow(Type t) { or isDeeplyConst(t.(GNUVectorType).getBaseType()) or + isDeeplyConst(t.(ScalableVectorType).getBaseType()) + or isDeeplyConst(t.(FunctionPointerIshType).getBaseType()) or isDeeplyConst(t.(PointerWrapper).getTemplateArgument(0)) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/internal/CppType.qll b/cpp/ql/lib/semmle/code/cpp/ir/internal/CppType.qll index d873e3ec757e..b25bb041f33c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/internal/CppType.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/internal/CppType.qll @@ -29,6 +29,10 @@ private int getTypeSizeWorkaround(Type type) { not arrayType.hasArraySize() and result = getPointerSize() ) + or + // Scalable vectors are opaque and not of fixed size. Use 0 as a substitute. + type instanceof ScalableVectorType and + result = 0 ) ) } @@ -136,6 +140,8 @@ private predicate isOpaqueType(Type type) { type instanceof PointerToMemberType // PTMs are missing size info or type instanceof ScalableVectorCount + or + type instanceof ScalableVectorType } /** diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 7a50fbe51de1..53ebaf2114ff 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -58,7 +58,7 @@ #-----| Type = [LongType] unsigned long #-----| getParameter(1): [Parameter] (unnamed parameter 1) #-----| Type = [ScopedEnum] align_val_t -arm.cpp: +arm_neon.cpp: # 6| [TopLevelFunction] uint8x8_t vadd_u8(uint8x8_t, uint8x8_t) # 6| : # 6| getParameter(0): [Parameter] a @@ -76,59 +76,105 @@ arm.cpp: # 7| getRightOperand(): [VariableAccess] b # 7| Type = [CTypedefType] uint8x8_t # 7| ValueCategory = prvalue(load) -# 12| [TopLevelFunction] uint16x8_t __builtin_aarch64_uaddlv8qi_uuu(uint8x8_t, uint8x8_t) +# 10| [TopLevelFunction] uint16x8_t vaddl_u8(uint8x8_t, uint8x8_t) +# 10| : +# 10| getParameter(0): [Parameter] a +# 10| Type = [CTypedefType] uint8x8_t +# 10| getParameter(1): [Parameter] b +# 10| Type = [CTypedefType] uint8x8_t +# 12| [TopLevelFunction] uint16x8_t arm_add(uint8x8_t, uint8x8_t*) # 12| : -# 12| getParameter(0): [Parameter] (unnamed parameter 0) -# 12| Type = [CTypedefType] uint8x8_t -# 12| getParameter(1): [Parameter] (unnamed parameter 1) +# 12| getParameter(0): [Parameter] a # 12| Type = [CTypedefType] uint8x8_t -# 14| [TopLevelFunction] uint16x8_t vaddl_u8(uint8x8_t, uint8x8_t) -# 14| : -# 14| getParameter(0): [Parameter] a -# 14| Type = [CTypedefType] uint8x8_t -# 14| getParameter(1): [Parameter] b -# 14| Type = [CTypedefType] uint8x8_t -# 14| getEntryPoint(): [BlockStmt] { ... } -# 15| getStmt(0): [ReturnStmt] return ... -# 15| getExpr(): [FunctionCall] call to __builtin_aarch64_uaddlv8qi_uuu -# 15| Type = [CTypedefType] uint16x8_t -# 15| ValueCategory = prvalue -# 15| getArgument(0): [VariableAccess] a -# 15| Type = [CTypedefType] uint8x8_t -# 15| ValueCategory = prvalue(load) -# 15| getArgument(1): [VariableAccess] b -# 15| Type = [CTypedefType] uint8x8_t -# 15| ValueCategory = prvalue(load) -# 18| [TopLevelFunction] uint16x8_t arm_add(uint8x8_t, uint8x8_t) -# 18| : -# 18| getParameter(0): [Parameter] a -# 18| Type = [CTypedefType] uint8x8_t -# 18| getParameter(1): [Parameter] b -# 18| Type = [CTypedefType] uint8x8_t -# 18| getEntryPoint(): [BlockStmt] { ... } -# 19| getStmt(0): [DeclStmt] declaration -# 19| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c -# 19| Type = [CTypedefType] uint8x8_t -# 19| getVariable().getInitializer(): [Initializer] initializer for c -# 19| getExpr(): [FunctionCall] call to vadd_u8 -# 19| Type = [CTypedefType] uint8x8_t -# 19| ValueCategory = prvalue -# 19| getArgument(0): [VariableAccess] a -# 19| Type = [CTypedefType] uint8x8_t -# 19| ValueCategory = prvalue(load) -# 19| getArgument(1): [VariableAccess] b -# 19| Type = [CTypedefType] uint8x8_t -# 19| ValueCategory = prvalue(load) -# 20| getStmt(1): [ReturnStmt] return ... -# 20| getExpr(): [FunctionCall] call to vaddl_u8 -# 20| Type = [CTypedefType] uint16x8_t -# 20| ValueCategory = prvalue -# 20| getArgument(0): [VariableAccess] a -# 20| Type = [CTypedefType] uint8x8_t -# 20| ValueCategory = prvalue(load) -# 20| getArgument(1): [VariableAccess] c -# 20| Type = [CTypedefType] uint8x8_t -# 20| ValueCategory = prvalue(load) +# 12| getParameter(1): [Parameter] b +# 12| Type = [PointerType] uint8x8_t * +# 12| getEntryPoint(): [BlockStmt] { ... } +# 13| getStmt(0): [DeclStmt] declaration +# 13| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c +# 13| Type = [CTypedefType] uint8x8_t +# 13| getVariable().getInitializer(): [Initializer] initializer for c +# 13| getExpr(): [FunctionCall] call to vadd_u8 +# 13| Type = [CTypedefType] uint8x8_t +# 13| ValueCategory = prvalue +# 13| getArgument(0): [VariableAccess] a +# 13| Type = [CTypedefType] uint8x8_t +# 13| ValueCategory = prvalue(load) +# 13| getArgument(1): [PointerDereferenceExpr] * ... +# 13| Type = [CTypedefType] uint8x8_t +# 13| ValueCategory = prvalue(load) +# 13| getOperand(): [VariableAccess] b +# 13| Type = [PointerType] uint8x8_t * +# 13| ValueCategory = prvalue(load) +# 14| getStmt(1): [ReturnStmt] return ... +# 14| getExpr(): [FunctionCall] call to vaddl_u8 +# 14| Type = [CTypedefType] uint16x8_t +# 14| ValueCategory = prvalue +# 14| getArgument(0): [VariableAccess] a +# 14| Type = [CTypedefType] uint8x8_t +# 14| ValueCategory = prvalue(load) +# 14| getArgument(1): [VariableAccess] c +# 14| Type = [CTypedefType] uint8x8_t +# 14| ValueCategory = prvalue(load) +# 20| [TopLevelFunction] mfloat8x8_t vreinterpret_mf8_s8(int8x8_t) +# 20| : +# 20| getParameter(0): [Parameter] (unnamed parameter 0) +# 20| Type = [CTypedefType] int8x8_t +# 22| [TopLevelFunction] mfloat8x8_t arm_reinterpret(int8x8_t*) +# 22| : +# 22| getParameter(0): [Parameter] a +# 22| Type = [PointerType] int8x8_t * +# 22| getEntryPoint(): [BlockStmt] { ... } +# 23| getStmt(0): [ReturnStmt] return ... +# 23| getExpr(): [FunctionCall] call to vreinterpret_mf8_s8 +# 23| Type = [CTypedefType] mfloat8x8_t +# 23| ValueCategory = prvalue +# 23| getArgument(0): [PointerDereferenceExpr] * ... +# 23| Type = [CTypedefType] int8x8_t +# 23| ValueCategory = prvalue(load) +# 23| getOperand(): [VariableAccess] a +# 23| Type = [PointerType] int8x8_t * +# 23| ValueCategory = prvalue(load) +arm_sve.cpp: +# 6| [TopLevelFunction] svuint8x2_t svsel_u8_x2(svcount_t, svuint8x2_t, svuint8x2_t) +# 6| : +# 6| getParameter(0): [Parameter] (unnamed parameter 0) +# 6| Type = [CTypedefType] svcount_t +# 6| getParameter(1): [Parameter] (unnamed parameter 1) +# 6| Type = [CTypedefType] svuint8x2_t +# 6| getParameter(2): [Parameter] (unnamed parameter 2) +# 6| Type = [CTypedefType] svuint8x2_t +# 8| [TopLevelFunction] svuint8x2_t arm_sel(svcount_t, svuint8x2_t, svuint8x2_t*) +# 8| : +# 8| getParameter(0): [Parameter] a +# 8| Type = [CTypedefType] svcount_t +# 8| getParameter(1): [Parameter] b +# 8| Type = [CTypedefType] svuint8x2_t +# 8| getParameter(2): [Parameter] c +# 8| Type = [PointerType] svuint8x2_t * +# 8| getEntryPoint(): [BlockStmt] { ... } +# 9| getStmt(0): [DeclStmt] declaration +# 9| getDeclarationEntry(0): [VariableDeclarationEntry] definition of d +# 9| Type = [CTypedefType] svuint8x2_t +# 9| getVariable().getInitializer(): [Initializer] initializer for d +# 9| getExpr(): [FunctionCall] call to svsel_u8_x2 +# 9| Type = [CTypedefType] svuint8x2_t +# 9| ValueCategory = prvalue +# 9| getArgument(0): [VariableAccess] a +# 9| Type = [CTypedefType] svcount_t +# 9| ValueCategory = prvalue(load) +# 9| getArgument(1): [VariableAccess] b +# 9| Type = [CTypedefType] svuint8x2_t +# 9| ValueCategory = prvalue(load) +# 9| getArgument(2): [PointerDereferenceExpr] * ... +# 9| Type = [CTypedefType] svuint8x2_t +# 9| ValueCategory = prvalue(load) +# 9| getOperand(): [VariableAccess] c +# 9| Type = [PointerType] svuint8x2_t * +# 9| ValueCategory = prvalue(load) +# 10| getStmt(1): [ReturnStmt] return ... +# 10| getExpr(): [VariableAccess] d +# 10| Type = [CTypedefType] svuint8x2_t +# 10| ValueCategory = prvalue(load) bad_asts.cpp: # 5| [CopyAssignmentOperator] Bad::S& Bad::S::operator=(Bad::S const&) # 5| : diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected index e258fd81f3ef..575631ab0417 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -1,4 +1,4 @@ -arm.cpp: +arm_neon.cpp: # 6| uint8x8_t vadd_u8(uint8x8_t, uint8x8_t) # 6| Block 0 # 6| v6_1(void) = EnterFunction : @@ -21,65 +21,107 @@ arm.cpp: # 6| v6_11(void) = AliasedUse : m6_3 # 6| v6_12(void) = ExitFunction : -# 14| uint16x8_t vaddl_u8(uint8x8_t, uint8x8_t) -# 14| Block 0 -# 14| v14_1(void) = EnterFunction : -# 14| m14_2(unknown) = AliasedDefinition : -# 14| m14_3(unknown) = InitializeNonLocal : -# 14| m14_4(unknown) = Chi : total:m14_2, partial:m14_3 -# 14| r14_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] : -# 14| m14_6(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r14_5 -# 14| r14_7(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] : -# 14| m14_8(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[b] : &:r14_7 -# 15| r15_1(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] : -# 15| r15_2(glval) = FunctionAddress[__builtin_aarch64_uaddlv8qi_uuu] : -# 15| r15_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] : -# 15| r15_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r15_3, m14_6 -# 15| r15_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] : -# 15| r15_6(__attribute((neon_vector_type(8))) unsigned char) = Load[b] : &:r15_5, m14_8 -# 15| r15_7(__attribute((neon_vector_type(8))) unsigned short) = Call[__builtin_aarch64_uaddlv8qi_uuu] : func:r15_2, 0:r15_4, 1:r15_6 -# 15| m15_8(unknown) = ^CallSideEffect : ~m14_4 -# 15| m15_9(unknown) = Chi : total:m14_4, partial:m15_8 -# 15| m15_10(__attribute((neon_vector_type(8))) unsigned short) = Store[#return] : &:r15_1, r15_7 -# 14| r14_9(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] : -# 14| v14_10(void) = ReturnValue : &:r14_9, m15_10 -# 14| v14_11(void) = AliasedUse : ~m15_9 -# 14| v14_12(void) = ExitFunction : - -# 18| uint16x8_t arm_add(uint8x8_t, uint8x8_t) -# 18| Block 0 -# 18| v18_1(void) = EnterFunction : -# 18| m18_2(unknown) = AliasedDefinition : -# 18| m18_3(unknown) = InitializeNonLocal : -# 18| m18_4(unknown) = Chi : total:m18_2, partial:m18_3 -# 18| r18_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] : -# 18| m18_6(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r18_5 -# 18| r18_7(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] : -# 18| m18_8(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[b] : &:r18_7 -# 19| r19_1(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] : -# 19| r19_2(glval) = FunctionAddress[vadd_u8] : -# 19| r19_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] : -# 19| r19_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r19_3, m18_6 -# 19| r19_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] : -# 19| r19_6(__attribute((neon_vector_type(8))) unsigned char) = Load[b] : &:r19_5, m18_8 -# 19| r19_7(__attribute((neon_vector_type(8))) unsigned char) = Call[vadd_u8] : func:r19_2, 0:r19_4, 1:r19_6 -# 19| m19_8(unknown) = ^CallSideEffect : ~m18_4 -# 19| m19_9(unknown) = Chi : total:m18_4, partial:m19_8 -# 19| m19_10(__attribute((neon_vector_type(8))) unsigned char) = Store[c] : &:r19_1, r19_7 -# 20| r20_1(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] : -# 20| r20_2(glval) = FunctionAddress[vaddl_u8] : -# 20| r20_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] : -# 20| r20_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r20_3, m18_6 -# 20| r20_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] : -# 20| r20_6(__attribute((neon_vector_type(8))) unsigned char) = Load[c] : &:r20_5, m19_10 -# 20| r20_7(__attribute((neon_vector_type(8))) unsigned short) = Call[vaddl_u8] : func:r20_2, 0:r20_4, 1:r20_6 -# 20| m20_8(unknown) = ^CallSideEffect : ~m19_9 -# 20| m20_9(unknown) = Chi : total:m19_9, partial:m20_8 -# 20| m20_10(__attribute((neon_vector_type(8))) unsigned short) = Store[#return] : &:r20_1, r20_7 -# 18| r18_9(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] : -# 18| v18_10(void) = ReturnValue : &:r18_9, m20_10 -# 18| v18_11(void) = AliasedUse : ~m20_9 -# 18| v18_12(void) = ExitFunction : +# 12| uint16x8_t arm_add(uint8x8_t, uint8x8_t*) +# 12| Block 0 +# 12| v12_1(void) = EnterFunction : +# 12| m12_2(unknown) = AliasedDefinition : +# 12| m12_3(unknown) = InitializeNonLocal : +# 12| m12_4(unknown) = Chi : total:m12_2, partial:m12_3 +# 12| r12_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] : +# 12| m12_6(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r12_5 +# 12| r12_7(glval<__attribute((neon_vector_type(8))) unsigned char *>) = VariableAddress[b] : +# 12| m12_8(__attribute((neon_vector_type(8))) unsigned char *) = InitializeParameter[b] : &:r12_7 +# 12| r12_9(__attribute((neon_vector_type(8))) unsigned char *) = Load[b] : &:r12_7, m12_8 +# 12| m12_10(unknown) = InitializeIndirection[b] : &:r12_9 +# 13| r13_1(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] : +# 13| r13_2(glval) = FunctionAddress[vadd_u8] : +# 13| r13_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] : +# 13| r13_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r13_3, m12_6 +# 13| r13_5(glval<__attribute((neon_vector_type(8))) unsigned char *>) = VariableAddress[b] : +# 13| r13_6(__attribute((neon_vector_type(8))) unsigned char *) = Load[b] : &:r13_5, m12_8 +# 13| r13_7(__attribute((neon_vector_type(8))) unsigned char) = Load[?] : &:r13_6, ~m12_10 +# 13| r13_8(__attribute((neon_vector_type(8))) unsigned char) = Call[vadd_u8] : func:r13_2, 0:r13_4, 1:r13_7 +# 13| m13_9(unknown) = ^CallSideEffect : ~m12_4 +# 13| m13_10(unknown) = Chi : total:m12_4, partial:m13_9 +# 13| m13_11(__attribute((neon_vector_type(8))) unsigned char) = Store[c] : &:r13_1, r13_8 +# 14| r14_1(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] : +# 14| r14_2(glval) = FunctionAddress[vaddl_u8] : +# 14| r14_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] : +# 14| r14_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r14_3, m12_6 +# 14| r14_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] : +# 14| r14_6(__attribute((neon_vector_type(8))) unsigned char) = Load[c] : &:r14_5, m13_11 +# 14| r14_7(__attribute((neon_vector_type(8))) unsigned short) = Call[vaddl_u8] : func:r14_2, 0:r14_4, 1:r14_6 +# 14| m14_8(unknown) = ^CallSideEffect : ~m13_10 +# 14| m14_9(unknown) = Chi : total:m13_10, partial:m14_8 +# 14| m14_10(__attribute((neon_vector_type(8))) unsigned short) = Store[#return] : &:r14_1, r14_7 +# 12| v12_11(void) = ReturnIndirection[b] : &:r12_9, m12_10 +# 12| r12_12(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] : +# 12| v12_13(void) = ReturnValue : &:r12_12, m14_10 +# 12| v12_14(void) = AliasedUse : ~m14_9 +# 12| v12_15(void) = ExitFunction : + +# 22| mfloat8x8_t arm_reinterpret(int8x8_t*) +# 22| Block 0 +# 22| v22_1(void) = EnterFunction : +# 22| m22_2(unknown) = AliasedDefinition : +# 22| m22_3(unknown) = InitializeNonLocal : +# 22| m22_4(unknown) = Chi : total:m22_2, partial:m22_3 +# 22| r22_5(glval) = VariableAddress[a] : +# 22| m22_6(char *) = InitializeParameter[a] : &:r22_5 +# 22| r22_7(char *) = Load[a] : &:r22_5, m22_6 +# 22| m22_8(unknown) = InitializeIndirection[a] : &:r22_7 +# 23| r23_1(glval<__mfp8>) = VariableAddress[#return] : +# 23| r23_2(glval) = FunctionAddress[vreinterpret_mf8_s8] : +# 23| r23_3(glval) = VariableAddress[a] : +# 23| r23_4(char *) = Load[a] : &:r23_3, m22_6 +# 23| r23_5(char) = Load[?] : &:r23_4, ~m22_8 +# 23| r23_6(__mfp8) = Call[vreinterpret_mf8_s8] : func:r23_2, 0:r23_5 +# 23| m23_7(unknown) = ^CallSideEffect : ~m22_4 +# 23| m23_8(unknown) = Chi : total:m22_4, partial:m23_7 +# 23| m23_9(__mfp8) = Store[#return] : &:r23_1, r23_6 +# 22| v22_9(void) = ReturnIndirection[a] : &:r22_7, m22_8 +# 22| r22_10(glval<__mfp8>) = VariableAddress[#return] : +# 22| v22_11(void) = ReturnValue : &:r22_10, m23_9 +# 22| v22_12(void) = AliasedUse : ~m23_8 +# 22| v22_13(void) = ExitFunction : + +arm_sve.cpp: +# 8| svuint8x2_t arm_sel(svcount_t, svuint8x2_t, svuint8x2_t*) +# 8| Block 0 +# 8| v8_1(void) = EnterFunction : +# 8| m8_2(unknown) = AliasedDefinition : +# 8| m8_3(unknown) = InitializeNonLocal : +# 8| m8_4(unknown) = Chi : total:m8_2, partial:m8_3 +# 8| r8_5(glval<__SVCount_t>) = VariableAddress[a] : +# 8| m8_6(__SVCount_t) = InitializeParameter[a] : &:r8_5 +# 8| r8_7(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[b] : +# 8| m8_8(__edg_scalable_vector_type__(unsigned char, 2)) = InitializeParameter[b] : &:r8_7 +# 8| r8_9(glval<__edg_scalable_vector_type__(unsigned char, 2) *>) = VariableAddress[c] : +# 8| m8_10(__edg_scalable_vector_type__(unsigned char, 2) *) = InitializeParameter[c] : &:r8_9 +# 8| r8_11(__edg_scalable_vector_type__(unsigned char, 2) *) = Load[c] : &:r8_9, m8_10 +# 8| m8_12(unknown) = InitializeIndirection[c] : &:r8_11 +# 9| r9_1(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[d] : +# 9| r9_2(glval) = FunctionAddress[svsel_u8_x2] : +# 9| r9_3(glval<__SVCount_t>) = VariableAddress[a] : +# 9| r9_4(__SVCount_t) = Load[a] : &:r9_3, m8_6 +# 9| r9_5(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[b] : +# 9| r9_6(__edg_scalable_vector_type__(unsigned char, 2)) = Load[b] : &:r9_5, m8_8 +# 9| r9_7(glval<__edg_scalable_vector_type__(unsigned char, 2) *>) = VariableAddress[c] : +# 9| r9_8(__edg_scalable_vector_type__(unsigned char, 2) *) = Load[c] : &:r9_7, m8_10 +# 9| r9_9(__edg_scalable_vector_type__(unsigned char, 2)) = Load[?] : &:r9_8, ~m8_12 +# 9| r9_10(__edg_scalable_vector_type__(unsigned char, 2)) = Call[svsel_u8_x2] : func:r9_2, 0:r9_4, 1:r9_6, 2:r9_9 +# 9| m9_11(unknown) = ^CallSideEffect : ~m8_4 +# 9| m9_12(unknown) = Chi : total:m8_4, partial:m9_11 +# 9| m9_13(__edg_scalable_vector_type__(unsigned char, 2)) = Store[d] : &:r9_1, r9_10 +# 10| r10_1(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[#return] : +# 10| r10_2(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[d] : +# 10| r10_3(__edg_scalable_vector_type__(unsigned char, 2)) = Load[d] : &:r10_2, m9_13 +# 10| m10_4(__edg_scalable_vector_type__(unsigned char, 2)) = Store[#return] : &:r10_1, r10_3 +# 8| v8_13(void) = ReturnIndirection[c] : &:r8_11, m8_12 +# 8| r8_14(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[#return] : +# 8| v8_15(void) = ReturnValue : &:r8_14, m10_4 +# 8| v8_16(void) = AliasedUse : ~m9_12 +# 8| v8_17(void) = ExitFunction : bad_asts.cpp: # 9| int Bad::S::MemberFunction(int) diff --git a/cpp/ql/test/library-tests/ir/ir/arm.cpp b/cpp/ql/test/library-tests/ir/ir/arm.cpp deleted file mode 100644 index 36e20715bc57..000000000000 --- a/cpp/ql/test/library-tests/ir/ir/arm.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// semmle-extractor-options: --edg --target --edg linux_arm64 - -typedef __Uint8x8_t uint8x8_t; -typedef __Uint16x8_t uint16x8_t; - -uint8x8_t vadd_u8(uint8x8_t a, uint8x8_t b) { - return a + b; -} - -// Workaround: the frontend only exposes this when the arm_neon.h -// header is encountered. -uint16x8_t __builtin_aarch64_uaddlv8qi_uuu(uint8x8_t, uint8x8_t); - -uint16x8_t vaddl_u8(uint8x8_t a, uint8x8_t b) { - return __builtin_aarch64_uaddlv8qi_uuu (a, b); -} - -uint16x8_t arm_add(uint8x8_t a, uint8x8_t b) { - uint8x8_t c = vadd_u8(a, b); - return vaddl_u8(a, c); -} diff --git a/cpp/ql/test/library-tests/ir/ir/arm_neon.cpp b/cpp/ql/test/library-tests/ir/ir/arm_neon.cpp new file mode 100644 index 000000000000..d1659dfba35a --- /dev/null +++ b/cpp/ql/test/library-tests/ir/ir/arm_neon.cpp @@ -0,0 +1,24 @@ +// semmle-extractor-options: --edg --target --edg linux_arm64 --gnu_version 150000 + +typedef __Uint8x8_t uint8x8_t; +typedef __Uint16x8_t uint16x8_t; + +uint8x8_t vadd_u8(uint8x8_t a, uint8x8_t b) { + return a + b; +} + +uint16x8_t vaddl_u8(uint8x8_t a, uint8x8_t b); + +uint16x8_t arm_add(uint8x8_t a, uint8x8_t *b) { + uint8x8_t c = vadd_u8(a, *b); + return vaddl_u8(a, c); +} + +typedef __attribute__((neon_vector_type(8))) __mfp8 mfloat8x8_t; +typedef __attribute__((neon_vector_type(8))) char int8x8_t; + +mfloat8x8_t vreinterpret_mf8_s8(int8x8_t); + +mfloat8x8_t arm_reinterpret(int8x8_t *a) { + return vreinterpret_mf8_s8(*a); +} diff --git a/cpp/ql/test/library-tests/ir/ir/arm_sve.cpp b/cpp/ql/test/library-tests/ir/ir/arm_sve.cpp new file mode 100644 index 000000000000..33bad8abbe4e --- /dev/null +++ b/cpp/ql/test/library-tests/ir/ir/arm_sve.cpp @@ -0,0 +1,11 @@ +// semmle-extractor-options: --edg --target --edg linux_arm64 --clang_version 190000 + +typedef __clang_svuint8x2_t svuint8x2_t; +typedef __SVCount_t svcount_t; + +svuint8x2_t svsel_u8_x2(svcount_t, svuint8x2_t, svuint8x2_t); + +svuint8x2_t arm_sel(svcount_t a, svuint8x2_t b, svuint8x2_t *c) { + svuint8x2_t d = svsel_u8_x2(a, b, *c); + return d; +} diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 97d7e7c43b48..e57a3bc11b5e 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -1,4 +1,4 @@ -arm.cpp: +arm_neon.cpp: # 6| uint8x8_t vadd_u8(uint8x8_t, uint8x8_t) # 6| Block 0 # 6| v6_1(void) = EnterFunction : @@ -20,60 +20,100 @@ arm.cpp: # 6| v6_10(void) = AliasedUse : ~m? # 6| v6_11(void) = ExitFunction : -# 14| uint16x8_t vaddl_u8(uint8x8_t, uint8x8_t) -# 14| Block 0 -# 14| v14_1(void) = EnterFunction : -# 14| mu14_2(unknown) = AliasedDefinition : -# 14| mu14_3(unknown) = InitializeNonLocal : -# 14| r14_4(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] : -# 14| mu14_5(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r14_4 -# 14| r14_6(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] : -# 14| mu14_7(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[b] : &:r14_6 -# 15| r15_1(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] : -# 15| r15_2(glval) = FunctionAddress[__builtin_aarch64_uaddlv8qi_uuu] : -# 15| r15_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] : -# 15| r15_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r15_3, ~m? -# 15| r15_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] : -# 15| r15_6(__attribute((neon_vector_type(8))) unsigned char) = Load[b] : &:r15_5, ~m? -# 15| r15_7(__attribute((neon_vector_type(8))) unsigned short) = Call[__builtin_aarch64_uaddlv8qi_uuu] : func:r15_2, 0:r15_4, 1:r15_6 -# 15| mu15_8(unknown) = ^CallSideEffect : ~m? -# 15| mu15_9(__attribute((neon_vector_type(8))) unsigned short) = Store[#return] : &:r15_1, r15_7 -# 14| r14_8(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] : -# 14| v14_9(void) = ReturnValue : &:r14_8, ~m? -# 14| v14_10(void) = AliasedUse : ~m? -# 14| v14_11(void) = ExitFunction : - -# 18| uint16x8_t arm_add(uint8x8_t, uint8x8_t) -# 18| Block 0 -# 18| v18_1(void) = EnterFunction : -# 18| mu18_2(unknown) = AliasedDefinition : -# 18| mu18_3(unknown) = InitializeNonLocal : -# 18| r18_4(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] : -# 18| mu18_5(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r18_4 -# 18| r18_6(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] : -# 18| mu18_7(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[b] : &:r18_6 -# 19| r19_1(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] : -# 19| r19_2(glval) = FunctionAddress[vadd_u8] : -# 19| r19_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] : -# 19| r19_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r19_3, ~m? -# 19| r19_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[b] : -# 19| r19_6(__attribute((neon_vector_type(8))) unsigned char) = Load[b] : &:r19_5, ~m? -# 19| r19_7(__attribute((neon_vector_type(8))) unsigned char) = Call[vadd_u8] : func:r19_2, 0:r19_4, 1:r19_6 -# 19| mu19_8(unknown) = ^CallSideEffect : ~m? -# 19| mu19_9(__attribute((neon_vector_type(8))) unsigned char) = Store[c] : &:r19_1, r19_7 -# 20| r20_1(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] : -# 20| r20_2(glval) = FunctionAddress[vaddl_u8] : -# 20| r20_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] : -# 20| r20_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r20_3, ~m? -# 20| r20_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] : -# 20| r20_6(__attribute((neon_vector_type(8))) unsigned char) = Load[c] : &:r20_5, ~m? -# 20| r20_7(__attribute((neon_vector_type(8))) unsigned short) = Call[vaddl_u8] : func:r20_2, 0:r20_4, 1:r20_6 -# 20| mu20_8(unknown) = ^CallSideEffect : ~m? -# 20| mu20_9(__attribute((neon_vector_type(8))) unsigned short) = Store[#return] : &:r20_1, r20_7 -# 18| r18_8(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] : -# 18| v18_9(void) = ReturnValue : &:r18_8, ~m? -# 18| v18_10(void) = AliasedUse : ~m? -# 18| v18_11(void) = ExitFunction : +# 12| uint16x8_t arm_add(uint8x8_t, uint8x8_t*) +# 12| Block 0 +# 12| v12_1(void) = EnterFunction : +# 12| mu12_2(unknown) = AliasedDefinition : +# 12| mu12_3(unknown) = InitializeNonLocal : +# 12| r12_4(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] : +# 12| mu12_5(__attribute((neon_vector_type(8))) unsigned char) = InitializeParameter[a] : &:r12_4 +# 12| r12_6(glval<__attribute((neon_vector_type(8))) unsigned char *>) = VariableAddress[b] : +# 12| mu12_7(__attribute((neon_vector_type(8))) unsigned char *) = InitializeParameter[b] : &:r12_6 +# 12| r12_8(__attribute((neon_vector_type(8))) unsigned char *) = Load[b] : &:r12_6, ~m? +# 12| mu12_9(unknown) = InitializeIndirection[b] : &:r12_8 +# 13| r13_1(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] : +# 13| r13_2(glval) = FunctionAddress[vadd_u8] : +# 13| r13_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] : +# 13| r13_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r13_3, ~m? +# 13| r13_5(glval<__attribute((neon_vector_type(8))) unsigned char *>) = VariableAddress[b] : +# 13| r13_6(__attribute((neon_vector_type(8))) unsigned char *) = Load[b] : &:r13_5, ~m? +# 13| r13_7(__attribute((neon_vector_type(8))) unsigned char) = Load[?] : &:r13_6, ~m? +# 13| r13_8(__attribute((neon_vector_type(8))) unsigned char) = Call[vadd_u8] : func:r13_2, 0:r13_4, 1:r13_7 +# 13| mu13_9(unknown) = ^CallSideEffect : ~m? +# 13| mu13_10(__attribute((neon_vector_type(8))) unsigned char) = Store[c] : &:r13_1, r13_8 +# 14| r14_1(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] : +# 14| r14_2(glval) = FunctionAddress[vaddl_u8] : +# 14| r14_3(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[a] : +# 14| r14_4(__attribute((neon_vector_type(8))) unsigned char) = Load[a] : &:r14_3, ~m? +# 14| r14_5(glval<__attribute((neon_vector_type(8))) unsigned char>) = VariableAddress[c] : +# 14| r14_6(__attribute((neon_vector_type(8))) unsigned char) = Load[c] : &:r14_5, ~m? +# 14| r14_7(__attribute((neon_vector_type(8))) unsigned short) = Call[vaddl_u8] : func:r14_2, 0:r14_4, 1:r14_6 +# 14| mu14_8(unknown) = ^CallSideEffect : ~m? +# 14| mu14_9(__attribute((neon_vector_type(8))) unsigned short) = Store[#return] : &:r14_1, r14_7 +# 12| v12_10(void) = ReturnIndirection[b] : &:r12_8, ~m? +# 12| r12_11(glval<__attribute((neon_vector_type(8))) unsigned short>) = VariableAddress[#return] : +# 12| v12_12(void) = ReturnValue : &:r12_11, ~m? +# 12| v12_13(void) = AliasedUse : ~m? +# 12| v12_14(void) = ExitFunction : + +# 22| mfloat8x8_t arm_reinterpret(int8x8_t*) +# 22| Block 0 +# 22| v22_1(void) = EnterFunction : +# 22| mu22_2(unknown) = AliasedDefinition : +# 22| mu22_3(unknown) = InitializeNonLocal : +# 22| r22_4(glval) = VariableAddress[a] : +# 22| mu22_5(char *) = InitializeParameter[a] : &:r22_4 +# 22| r22_6(char *) = Load[a] : &:r22_4, ~m? +# 22| mu22_7(unknown) = InitializeIndirection[a] : &:r22_6 +# 23| r23_1(glval<__mfp8>) = VariableAddress[#return] : +# 23| r23_2(glval) = FunctionAddress[vreinterpret_mf8_s8] : +# 23| r23_3(glval) = VariableAddress[a] : +# 23| r23_4(char *) = Load[a] : &:r23_3, ~m? +# 23| r23_5(char) = Load[?] : &:r23_4, ~m? +# 23| r23_6(__mfp8) = Call[vreinterpret_mf8_s8] : func:r23_2, 0:r23_5 +# 23| mu23_7(unknown) = ^CallSideEffect : ~m? +# 23| mu23_8(__mfp8) = Store[#return] : &:r23_1, r23_6 +# 22| v22_8(void) = ReturnIndirection[a] : &:r22_6, ~m? +# 22| r22_9(glval<__mfp8>) = VariableAddress[#return] : +# 22| v22_10(void) = ReturnValue : &:r22_9, ~m? +# 22| v22_11(void) = AliasedUse : ~m? +# 22| v22_12(void) = ExitFunction : + +arm_sve.cpp: +# 8| svuint8x2_t arm_sel(svcount_t, svuint8x2_t, svuint8x2_t*) +# 8| Block 0 +# 8| v8_1(void) = EnterFunction : +# 8| mu8_2(unknown) = AliasedDefinition : +# 8| mu8_3(unknown) = InitializeNonLocal : +# 8| r8_4(glval<__SVCount_t>) = VariableAddress[a] : +# 8| mu8_5(__SVCount_t) = InitializeParameter[a] : &:r8_4 +# 8| r8_6(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[b] : +# 8| mu8_7(__edg_scalable_vector_type__(unsigned char, 2)) = InitializeParameter[b] : &:r8_6 +# 8| r8_8(glval<__edg_scalable_vector_type__(unsigned char, 2) *>) = VariableAddress[c] : +# 8| mu8_9(__edg_scalable_vector_type__(unsigned char, 2) *) = InitializeParameter[c] : &:r8_8 +# 8| r8_10(__edg_scalable_vector_type__(unsigned char, 2) *) = Load[c] : &:r8_8, ~m? +# 8| mu8_11(unknown) = InitializeIndirection[c] : &:r8_10 +# 9| r9_1(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[d] : +# 9| r9_2(glval) = FunctionAddress[svsel_u8_x2] : +# 9| r9_3(glval<__SVCount_t>) = VariableAddress[a] : +# 9| r9_4(__SVCount_t) = Load[a] : &:r9_3, ~m? +# 9| r9_5(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[b] : +# 9| r9_6(__edg_scalable_vector_type__(unsigned char, 2)) = Load[b] : &:r9_5, ~m? +# 9| r9_7(glval<__edg_scalable_vector_type__(unsigned char, 2) *>) = VariableAddress[c] : +# 9| r9_8(__edg_scalable_vector_type__(unsigned char, 2) *) = Load[c] : &:r9_7, ~m? +# 9| r9_9(__edg_scalable_vector_type__(unsigned char, 2)) = Load[?] : &:r9_8, ~m? +# 9| r9_10(__edg_scalable_vector_type__(unsigned char, 2)) = Call[svsel_u8_x2] : func:r9_2, 0:r9_4, 1:r9_6, 2:r9_9 +# 9| mu9_11(unknown) = ^CallSideEffect : ~m? +# 9| mu9_12(__edg_scalable_vector_type__(unsigned char, 2)) = Store[d] : &:r9_1, r9_10 +# 10| r10_1(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[#return] : +# 10| r10_2(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[d] : +# 10| r10_3(__edg_scalable_vector_type__(unsigned char, 2)) = Load[d] : &:r10_2, ~m? +# 10| mu10_4(__edg_scalable_vector_type__(unsigned char, 2)) = Store[#return] : &:r10_1, r10_3 +# 8| v8_12(void) = ReturnIndirection[c] : &:r8_10, ~m? +# 8| r8_13(glval<__edg_scalable_vector_type__(unsigned char, 2)>) = VariableAddress[#return] : +# 8| v8_14(void) = ReturnValue : &:r8_13, ~m? +# 8| v8_15(void) = AliasedUse : ~m? +# 8| v8_16(void) = ExitFunction : bad_asts.cpp: # 9| int Bad::S::MemberFunction(int)