From 3a09f7183094e749d86b0866fa9e1bb365d2fbc2 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sun, 11 Sep 2022 02:28:12 +0200 Subject: [PATCH] Added initial intvec/floatvec operator --- lib/std/bits.c3 | 20 ++- lib/std/core/types.c3 | 25 +++- lib/std/math.c3 | 57 +++++--- lib/std/math.matrix.c3 | 16 +-- src/compiler/compiler_internal.h | 6 + src/compiler/enums.h | 2 +- src/compiler/sema_decls.c | 129 +++++++++++++++++- src/compiler/sema_expr.c | 24 +++- src/compiler/sema_internal.h | 1 + src/compiler/symtab.c | 8 +- src/version.h | 2 +- .../test_suite/import/access_other_module.c3t | 17 ++- test/test_suite/operators/invalid_op_vec.c3 | 7 + .../import/access_other_module.c3t | 15 +- test/test_suite2/operators/invalid_op_vec.c3 | 7 + 15 files changed, 265 insertions(+), 71 deletions(-) create mode 100644 test/test_suite/operators/invalid_op_vec.c3 create mode 100644 test/test_suite2/operators/invalid_op_vec.c3 diff --git a/lib/std/bits.c3 b/lib/std/bits.c3 index 3ac45d35e..f4de89f87 100644 --- a/lib/std/bits.c3 +++ b/lib/std/bits.c3 @@ -3,7 +3,7 @@ module std::bits; /** * @require types::is_intlike($typeof(i)) `The input must be an integer or integer vector` **/ -macro popcount(i) +macro popcount(i) @operator(intvec) { return $$popcount(i); } @@ -27,7 +27,7 @@ macro bswap(i) @builtin /** * @require types::is_intlike($typeof(i)) `The input must be an integer or integer vector` **/ -macro ctz(i) @builtin +macro ctz(i) @operator(intvec) @builtin { return $$ctz(i); } @@ -35,15 +35,14 @@ macro ctz(i) @builtin /** * @require types::is_intlike($typeof(i)) `The input must be an integer or integer vector` **/ -macro clz(i) @builtin +macro clz(i) @operator(intvec) @builtin { return $$clz(i); } /** * @require types::is_intlike($typeof(hi)) && types::is_intlike($typeof(lo)) && types::is_intlike($typeof(shift)) `The input must be an integer or integer vector` - * @require types::is_same_type(hi, lo) `Hi and low arguments must have the same type` - * @require types::is_same_type(hi, shift) `The shift value must have the same type as shifted types` + * @require types::@has_same(hi, lo, shift) `Hi, low and shift arguments must have the same type` **/ macro fshl(hi, lo, shift) @builtin { @@ -52,8 +51,7 @@ macro fshl(hi, lo, shift) @builtin /** * @require types::is_intlike($typeof(hi)) && types::is_intlike($typeof(lo)) && types::is_intlike($typeof(shift)) `The input must be an integer or integer vector` - * @require types::is_same_type(hi, lo) `Hi and low arguments must have the same type` - * @require types::is_same_type(hi, shift) `The shift value must have the same type as shifted types` + * @require types::@has_same(hi, lo, shift) `Hi, low and shift arguments must have the same type` **/ macro fshr(hi, lo, shift) @builtin { @@ -62,18 +60,18 @@ macro fshr(hi, lo, shift) @builtin /** * @require types::is_intlike($typeof(i)) && types::is_intlike($typeof(shift)) `The input must be an integer or integer vector` - * @require types::is_same_type(i, shift) `The shift value must have the same type as shifted types` + * @require types::@has_same(i, shift) `The shift value must have the same type as shifted types` **/ -macro rotl(i, shift) @builtin +macro rotl(i, shift) @operator(intvec) @builtin { return $$fshl(i, i, shift); } /** * @require types::is_intlike($typeof(i)) && types::is_intlike($typeof(shift)) `The input must be an integer or integer vector` - * @require types::is_same_type(i, shift) `The shift value must have the same type as shifted types` + * @require types::@has_same(i, shift) `The shift value must have the same type as shifted types` **/ -macro rotr(i, shift) @builtin +macro rotr(i, shift) @operator(intvec) @builtin { return $$fshr(i, i, shift); } diff --git a/lib/std/core/types.c3 b/lib/std/core/types.c3 index 465e234f4..1426afe7b 100644 --- a/lib/std/core/types.c3 +++ b/lib/std/core/types.c3 @@ -134,6 +134,18 @@ macro bool is_intlike($Type) $endswitch; } +macro bool is_floatlike($Type) +{ + $switch ($Type.kind): + $case FLOAT: + return true; + $case VECTOR: + return $Type.inner.kind == TypeKind.FLOAT; + $default: + return false; + $endswitch; +} + macro bool is_vector($Type) { return $Type.kind == TypeKind.VECTOR; @@ -144,9 +156,18 @@ macro bool is_same($TypeA, $TypeB) return $TypeA.typeid == $TypeB.typeid; } -macro bool is_same_type(a, b) +macro bool @has_same(#a, #b, ...) { - return $typeof(a).typeid == $typeof(b).typeid; + var $type_a = $typeof(#a).typeid; + $if ($type_a != $typeof(#b).typeid): + return false; + $endif; + $for (var $i = 0; $i < $vacount; $i++): + $if ($typeof($vaexpr($i)).typeid != $type_a): + return false; + $endif; + $endfor; + return true; } macro bool is_equatable_value(value) diff --git a/lib/std/math.c3 b/lib/std/math.c3 index e3e9afd9f..a6ab90af4 100644 --- a/lib/std/math.c3 +++ b/lib/std/math.c3 @@ -96,47 +96,60 @@ fn double log2(double x) @inline return $$log2(x); } -fn double log(double x) @inline +/** + * @require types::is_floatlike($typeof(f)) `The input must be a floating point value or float vector` + **/ +macro log(f) { - return $$log(x); + return $$log(f); } -fn double cos(double x) @inline +/** + * @require types::is_floatlike($typeof(f)) `The input must be a floating point value or float vector` + **/ +macro cos(f) { - return $$cos(x); + return $$cos(f); } -fn float cosf(float x) @inline + +/** + * @require types::is_floatlike($typeof(f)) `The input must be a floating point value or float vector` + **/ +macro sin(f) { - return $$cos(x); + return $$sin(f); } -fn double sin(double x) @inline +/** + * @require types::is_floatlike($typeof(f)) `The input must be a floating point value or float vector` + **/ +macro exp(f) { - return $$sin(x); + return $$exp(f); } -fn float sinf(float x) @inline +/** + * @require types::is_floatlike($typeof(f)) `The input must be a floating point value or float vector` + * @require types::@has_same(f, exp) `Parameters must have the same type` + **/ +macro pow(f, exp) @operator(floatvec) { - return $$sin(x); + return $$pow(f, exp); } -fn double exp(double x) @inline -{ - return $$exp(x); -} - -fn double pow(double x, double y) @inline -{ - return $$pow(x, y); -} - -fn double trunc(double x) @inline +/** + * @require types::is_floatlike($typeof(f)) `The input must be a floating point value or float vector` + **/ +macro trunc(x) @operator(floatvec) { return $$trunc(x); } -fn double ceil(double x) @inline +/** + * @require types::is_floatlike($typeof(f)) `The input must be a floating point value or float vector` + **/ +macro ceil(x) @operator(floatvec) { return $$ceil(x); } diff --git a/lib/std/math.matrix.c3 b/lib/std/math.matrix.c3 index 05be57666..eaaf9a5ee 100644 --- a/lib/std/math.matrix.c3 +++ b/lib/std/math.matrix.c3 @@ -341,8 +341,8 @@ fn Matrix4x4 Matrix4x4.translate(Matrix4x4* m, float[<3>] v) fn Matrix3x3 Matrix3x3.rotate(Matrix3x3* m, float r) { return m.mul(Matrix3x3 { - math::cosf(r), -math::sinf(r), 0, - math::sinf(r), math::cosf(r), 0, + math::cos(r), -math::sin(r), 0, + math::sin(r), math::cos(r), 0, 0, 0, 1, }); } @@ -351,8 +351,8 @@ fn Matrix3x3 Matrix3x3.rotate(Matrix3x3* m, float r) fn Matrix4x4 Matrix4x4.rotate_z(Matrix4x4* m, float r) { return m.mul(Matrix4x4 { - math::cosf(r), -math::sinf(r), 0, 0, - math::sinf(r), math::cosf(r), 0, 0, + math::cos(r), -math::sin(r), 0, 0, + math::sin(r), math::cos(r), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, }); @@ -362,9 +362,9 @@ fn Matrix4x4 Matrix4x4.rotate_z(Matrix4x4* m, float r) fn Matrix4x4 Matrix4x4.rotate_y(Matrix4x4* m, float r) { return m.mul(Matrix4x4 { - math::cosf(r), 0, -math::sinf(r), 0, + math::cos(r), 0, -math::sin(r), 0, 0, 1, 0, 0, - math::sinf(r), 0, math::cosf(r), 0, + math::sin(r), 0, math::cos(r), 0, 0, 0, 0, 1, }); } @@ -374,8 +374,8 @@ fn Matrix4x4 Matrix4x4.rotate_x(Matrix4x4* m, float r) { return m.mul(Matrix4x4 { 1, 0, 0, 0, - 0, math::cosf(r), -math::sinf(r), 0, - 0, math::sinf(r), math::cosf(r), 0, + 0, math::cos(r), -math::sin(r), 0, + 0, math::sin(r), math::cos(r), 0, 0, 0, 0, 1, }); } diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index b5d334fe2..66b98d146 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -532,6 +532,8 @@ typedef struct }; struct { + bool attr_intvec : 1; + bool attr_floatvec : 1; DeclId body_param; CompilationUnit *unit; }; @@ -1438,6 +1440,8 @@ typedef struct Module_ Ast **files; // Asts Decl** method_extensions; + Decl** intvec_extensions; + Decl** floatvec_extensions; Decl** generic_cache; HTable symbols; struct CompilationUnit_ **units; @@ -1804,6 +1808,8 @@ extern const char *kw_out; extern const char *kw_inout; extern const char *kw_deprecated; extern const char *kw_distinct; +extern const char *kw_intvec; +extern const char *kw_floatvec; extern const char *kw_inline; extern const char *kw_inf; extern const char *kw_kind; diff --git a/src/compiler/enums.h b/src/compiler/enums.h index cde9152e6..e36e9c623 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -720,7 +720,7 @@ typedef enum OVERLOAD_ELEMENT_AT = 1, OVERLOAD_ELEMENT_REF, OVERLOAD_ELEMENT_SET, - OVERLOAD_LEN + OVERLOAD_LEN, } OperatorOverload; typedef enum diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 03fdd1d85..84d78f7a7 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -185,7 +185,7 @@ static bool sema_analyse_union_members(SemaContext *context, Decl *decl, Decl ** if (decl->is_packed && !decl->alignment) decl->alignment = 1; // 2. Otherwise pick the highest of the natural alignment and the given alignment. - if (!decl->is_packed) decl->alignment = MAX(decl->alignment, max_alignment); + if (!decl->is_packed && decl->alignment < max_alignment) decl->alignment = max_alignment; // We're only packed if the max alignment is > 1 decl->is_packed = decl->is_packed && max_alignment > 1; @@ -333,7 +333,7 @@ static bool sema_analyse_struct_members(SemaContext *context, Decl *decl, Decl * if (decl->is_packed && !decl->alignment) decl->alignment = 1; // 2. Otherwise pick the highest of the natural alignment and the given alignment. - if (!decl->is_packed) decl->alignment = MAX(decl->alignment, natural_alignment); + if (!decl->is_packed && decl->alignment < natural_alignment) decl->alignment = natural_alignment; // We must now possibly add the end padding. // First we calculate the actual size @@ -1172,6 +1172,68 @@ Decl *sema_find_operator(SemaContext *context, Expr *expr, OperatorOverload oper return NULL; } +INLINE Decl *sema_find_vec_operator_in_module(Module *module, const char *kw, bool is_int, bool allow_private, Decl *prev, Decl **private, SourceSpan span) +{ + Decl **funcs = is_int ? module->intvec_extensions : module->floatvec_extensions; + Decl *found = NULL; + FOREACH_BEGIN(Decl *func, funcs) + if (func->name == kw) + { + if (func->visibility != VISIBLE_PUBLIC && !allow_private) + { + if (!prev) *private = func; + continue; + } + found = func; + // Assume only one per module. + break; + } + FOREACH_END(); + if (!found) return prev; + *private = NULL; + if (prev) + { + sema_error_at(span, "Ambiguous name '%s', try to import fewer modules.", kw); + return poisoned_decl; + } + return found; +} + +INLINE Decl *sema_find_vec_operator_in_module_recursively(Module *module, const char *kw, bool is_int, bool allow_private, Decl *prev, Decl **private_ref, SourceSpan span) +{ + Decl *decl = sema_find_vec_operator_in_module(module, kw, is_int, allow_private, prev, private_ref, span); + if (decl) return decl; + FOREACH_BEGIN(Module *sub_module, module->sub_modules) + decl = sema_find_vec_operator_in_module(sub_module, kw, is_int, false, decl, private_ref, span); + if (!decl) continue; + if (!decl_ok(decl)) return decl; + FOREACH_END(); + return decl; +} + +Decl *sema_find_vec_operator(SemaContext *context, const char *kw, Type *base_type, SourceSpan span) +{ + bool is_int = type_is_integer(base_type); + Decl *private = NULL; + Decl *decl = sema_find_vec_operator_in_module(context->compilation_unit->module, kw, is_int, true, NULL, &private, span); + if (decl) return decl; + + Decl **imports = context->unit->imports; + FOREACH_BEGIN(Decl *import, context->unit->imports) + Module *imported_module = import->import.module; + bool is_private = import->import.private; + decl = sema_find_vec_operator_in_module_recursively(imported_module, kw, is_int, is_private, decl, &private, span); + if (!decl) continue; + if (!decl_ok(decl)) return decl; + FOREACH_END(); + if (!decl && private) + { + sema_error_at(span, "The vector operator '%s' could not be found except the private implementation in '%s'.", private->unit->module->name->module); + return poisoned_decl; + } + return decl; +} + static inline bool sema_analyse_operator_element_at(Decl *method) { @@ -1223,9 +1285,8 @@ static bool sema_check_operator_method_validity(Decl *method) return sema_analyse_operator_element_at(method); case OVERLOAD_LEN: return sema_analyse_operator_len(method); - default: - UNREACHABLE } + UNREACHABLE } static inline bool unit_add_method_like(CompilationUnit *unit, Type *parent_type, Decl *method_like) @@ -1443,20 +1504,68 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, const char *kw = expr->identifier_expr.ident; if (kw == kw_elementat) { + if (!decl->func_decl.type_parent) + { + SEMA_ERROR(expr, "@operator(elementat) can only be used with methods."); + return false; + } decl->operator = OVERLOAD_ELEMENT_AT; } else if (kw == kw_elementref) { + if (!decl->func_decl.type_parent) + { + SEMA_ERROR(expr, "@operator(elementref) can only be used with methods."); + return false; + } decl->operator = OVERLOAD_ELEMENT_REF; } else if (kw == kw_elementset) { + if (!decl->func_decl.type_parent) + { + SEMA_ERROR(expr, "@operator(elementset) can only be used with methods."); + return false; + } decl->operator = OVERLOAD_ELEMENT_SET; } else if (kw == kw_len) { + if (!decl->func_decl.type_parent) + { + SEMA_ERROR(expr, "@operator(len) can only be used with methods."); + return false; + } decl->operator = OVERLOAD_LEN; } + else if (kw == kw_floatvec) + { + if (decl->decl_kind != DECL_MACRO) + { + SEMA_ERROR(expr, "@operator(floatvec) can only be used with macros."); + return false; + } + if (decl->func_decl.type_parent) + { + SEMA_ERROR(expr, "@operator(floatvec) cannot be used with methods."); + return false; + } + decl->func_decl.attr_floatvec = true; + } + else if (kw == kw_intvec) + { + if (decl->decl_kind != DECL_MACRO) + { + SEMA_ERROR(expr, "@operator(intvec) can only be used with macros."); + return false; + } + if (decl->func_decl.type_parent) + { + SEMA_ERROR(expr, "@operator(intvec) cannot be used with methods."); + return false; + } + decl->func_decl.attr_intvec = true; + } else { goto FAILED_OP_TYPE; @@ -2037,7 +2146,6 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl) } Decl **parameters = decl->func_decl.signature.params; - unsigned param_count = vec_size(parameters); DeclId body_param = decl->func_decl.body_param; Decl **body_parameters = body_param ? declptr(body_param)->body_params : NULL; @@ -2080,6 +2188,17 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl) { if (!sema_analyse_macro_method(context, decl)) return decl_poison(decl); } + else + { + if (decl->func_decl.attr_floatvec) + { + vec_add(context->unit->module->floatvec_extensions, decl); + } + if (decl->func_decl.attr_intvec) + { + vec_add(context->unit->module->intvec_extensions, decl); + } + } decl->type = type_void; return true; } diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 7f8f634d6..1599a4462 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -4,6 +4,7 @@ #include "sema_internal.h" #include + /* * TODOs * - Disallow jumping in and out of an expression block. @@ -2846,12 +2847,18 @@ static inline bool sema_expr_analyse_call(SemaContext *context, Expr *expr) switch (decl->decl_kind) { case DECL_MACRO: + if (decl->func_decl.attr_intvec || decl->func_decl.attr_floatvec) + { + struct_var = func_expr->access_expr.parent; + break; + } + FALLTHROUGH; case DECL_FUNC: + struct_var = func_expr->access_expr.parent; if (decl->func_decl.signature.params[0]->type->type_kind == TYPE_POINTER) { - expr_insert_addr(func_expr->access_expr.parent); + expr_insert_addr(struct_var); } - struct_var = func_expr->access_expr.parent; break; default: break; @@ -4096,6 +4103,19 @@ CHECK_DEEPER: } } + if (type_flat_is_vector(type)) + { + Type *vec = type_flatten(type); + assert(vec->type_kind == TYPE_VECTOR); + Type *base = vec->array.base; + Decl *func = sema_find_vec_operator(context, kw, base, expr->span); + if (!decl_ok(func)) return false; + if (func) + { + expr->access_expr.ref = func; + return true; + } + } // 9. At this point we may only have distinct, struct, union, error, enum if (!type_may_have_sub_elements(type)) { diff --git a/src/compiler/sema_internal.h b/src/compiler/sema_internal.h index 47a37b6bc..c2fde42d4 100644 --- a/src/compiler/sema_internal.h +++ b/src/compiler/sema_internal.h @@ -73,6 +73,7 @@ void sema_analysis_pass_ct_assert(Module *module); void sema_analysis_pass_functions(Module *module); void sema_analyze_stage(Module *module, AnalysisStage stage); Decl *sema_find_operator(SemaContext *context, Expr *expr, OperatorOverload operator_overload); +Decl *sema_find_vec_operator(SemaContext *context, const char *kw, Type *base_type, SourceSpan span); bool sema_insert_method_call(SemaContext *context, Expr *method_call, Decl *method_decl, Expr *parent, Expr **arguments); bool sema_analyse_expr_lvalue(SemaContext *context, Expr *expr); bool sema_analyse_expr_lvalue_fold_const(SemaContext *context, Expr *expr); diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index 94ffdbfed..94fc20b11 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -60,12 +60,14 @@ const char *kw_elementat; const char *kw_elementref; const char *kw_elementset; const char *kw_elements; +const char *kw_floatvec; +const char *kw_in; const char *kw_incr; const char *kw_inf; const char *kw_inline; const char *kw_inner; const char *kw_inout; -const char *kw_in; +const char *kw_intvec; const char *kw_kind; const char *kw_len; const char *kw_mainstub; @@ -148,12 +150,14 @@ void symtab_init(uint32_t capacity) kw_elementref = KW_DEF("elementref"); kw_elementset = KW_DEF("elementset"); kw_elements = KW_DEF("elements"); + kw_floatvec = KW_DEF("floatvec"); + kw_in = KW_DEF("in"); kw_incr = KW_DEF("incr"); kw_inf = KW_DEF("inf"); kw_inline = KW_DEF("inline"); kw_inner = KW_DEF("inner"); kw_inout = KW_DEF("inout"); - kw_in = KW_DEF("in"); + kw_intvec = KW_DEF("intvec"); kw_kind = KW_DEF("kind"); kw_len = KW_DEF("len"); kw_mainstub = KW_DEF("_$mainstub"); diff --git a/src/version.h b/src/version.h index 96d87cd96..d6259dea1 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.3.38" \ No newline at end of file +#define COMPILER_VERSION "0.3.39" \ No newline at end of file diff --git a/test/test_suite/import/access_other_module.c3t b/test/test_suite/import/access_other_module.c3t index b78189bd8..71cf2d00d 100644 --- a/test/test_suite/import/access_other_module.c3t +++ b/test/test_suite/import/access_other_module.c3t @@ -1,24 +1,23 @@ // #target: macos-x64 module foo; -import std::math; +import libc; fn void main() { - void* foekf = &math::log; - double* xok = &math::DIV_1_SQRT2; + void* foekf = &libc::printf; + int* xok = &libc::EXIT_SUCCESS; } /* #expect: foo.ll - -@std_math_DIV_1_SQRT2 = external global double +@libc_EXIT_SUCCESS = external global i32, align 4 define void @foo_main() #0 { entry: %foekf = alloca i8*, align 8 - %xok = alloca double*, align 8 - store i8* bitcast (double (double)* @std_math_log to i8*), i8** %foekf, align 8 - store double* @std_math_DIV_1_SQRT2, double** %xok, align 8 + %xok = alloca i32*, align 8 + store i8* bitcast (i32 (i8*, ...)* @printf to i8*), i8** %foekf, align 8 + store i32* @libc_EXIT_SUCCESS, i32** %xok, align 8 ret void } -declare double @std_math_log(double) \ No newline at end of file +declare i32 @printf(i8*, ...) \ No newline at end of file diff --git a/test/test_suite/operators/invalid_op_vec.c3 b/test/test_suite/operators/invalid_op_vec.c3 new file mode 100644 index 000000000..f4c98cb5e --- /dev/null +++ b/test/test_suite/operators/invalid_op_vec.c3 @@ -0,0 +1,7 @@ +struct Foo { int x; } + +fn void Foo.test(Foo f) @operator(intvec) {} // #error: @operator(intvec) can only be used with macros. +fn void Foo.test(Foo f) @operator(floatvec) {} // #error: @operator(floatvec) can only be used with macros. +macro void Foo.test(Foo f) @operator(intvec) {} // #error: @operator(intvec) cannot be used with methods +macro void Foo.test(Foo f) @operator(floatvec) {} // #error: @operator(floatvec) cannot be used with methods + diff --git a/test/test_suite2/import/access_other_module.c3t b/test/test_suite2/import/access_other_module.c3t index 824309efe..afc52275e 100644 --- a/test/test_suite2/import/access_other_module.c3t +++ b/test/test_suite2/import/access_other_module.c3t @@ -1,24 +1,23 @@ // #target: macos-x64 module foo; -import std::math; +import libc; fn void main() { - void* foekf = &math::log; - double* xok = &math::DIV_1_SQRT2; + void* foekf = &libc::printf; + int* xok = &libc::EXIT_SUCCESS; } /* #expect: foo.ll - -@std_math_DIV_1_SQRT2 = external global double, align 8 +@libc_EXIT_SUCCESS = external global i32, align 4 define void @foo_main() #0 { entry: %foekf = alloca ptr, align 8 %xok = alloca ptr, align 8 - store ptr @std_math_log, ptr %foekf, align 8 - store ptr @std_math_DIV_1_SQRT2, ptr %xok, align 8 + store ptr @printf, ptr %foekf, align 8 + store ptr @libc_EXIT_SUCCESS, ptr %xok, align 8 ret void } -declare double @std_math_log(double) \ No newline at end of file +declare i32 @printf(ptr, ...) \ No newline at end of file diff --git a/test/test_suite2/operators/invalid_op_vec.c3 b/test/test_suite2/operators/invalid_op_vec.c3 new file mode 100644 index 000000000..f4c98cb5e --- /dev/null +++ b/test/test_suite2/operators/invalid_op_vec.c3 @@ -0,0 +1,7 @@ +struct Foo { int x; } + +fn void Foo.test(Foo f) @operator(intvec) {} // #error: @operator(intvec) can only be used with macros. +fn void Foo.test(Foo f) @operator(floatvec) {} // #error: @operator(floatvec) can only be used with macros. +macro void Foo.test(Foo f) @operator(intvec) {} // #error: @operator(intvec) cannot be used with methods +macro void Foo.test(Foo f) @operator(floatvec) {} // #error: @operator(floatvec) cannot be used with methods +