Skip to content

Commit

Permalink
[clang][WebAssembly] Implement support for table types and builtins
Browse files Browse the repository at this point in the history
This commit implements support for WebAssembly table types and
respective builtins. Table tables are WebAssembly objects to store
reference types. They have a large amount of semantic restrictions
including, but not limited to, only being allowed to be declared
at the top-level as static arrays of zero-length. Not being arguments
or result of functions, not being stored ot memory, etc.

This commit introduces the __attribute__((wasm_table)) to attach to
arrays of WebAssembly reference types. And the following builtins to
manage tables:

* ref   __builtin_wasm_table_get(table, idx)
* void  __builtin_wasm_table_set(table, idx, ref)
* uint  __builtin_wasm_table_size(table)
* uint  __builtin_wasm_table_grow(table, ref, uint)
* void  __builtin_wasm_table_fill(table, idx, ref, uint)
* void  __builtin_wasm_table_copy(table, table, uint, uint, uint)

This commit also enables reference-types feature at bleeding-edge.

This is joint work with Alex Bradbury (@asb).
  • Loading branch information
pmatos committed Nov 23, 2022
1 parent 51984e4 commit 8e3d6dd
Show file tree
Hide file tree
Showing 39 changed files with 1,018 additions and 204 deletions.
4 changes: 4 additions & 0 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1536,6 +1536,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
Expr *SizeExpr,
SourceLocation AttrLoc) const;

/// Return the unique reference to the Wasm table type of the specified
/// element type
QualType getWasmTableType(QualType EltTy) const;

/// Return the unique reference to the matrix type of the specified element
/// type and size
///
Expand Down
12 changes: 6 additions & 6 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -2663,7 +2663,7 @@ class ArraySubscriptExpr : public Expr {
: Expr(ArraySubscriptExprClass, t, VK, OK) {
SubExprs[LHS] = lhs;
SubExprs[RHS] = rhs;
ArrayOrMatrixSubscriptExprBits.RBracketLoc = rbracketloc;
AMTSubscriptExprBits.RBracketLoc = rbracketloc;
setDependence(computeDependence(this));
}

Expand Down Expand Up @@ -2700,10 +2700,10 @@ class ArraySubscriptExpr : public Expr {
SourceLocation getEndLoc() const { return getRBracketLoc(); }

SourceLocation getRBracketLoc() const {
return ArrayOrMatrixSubscriptExprBits.RBracketLoc;
return AMTSubscriptExprBits.RBracketLoc;
}
void setRBracketLoc(SourceLocation L) {
ArrayOrMatrixSubscriptExprBits.RBracketLoc = L;
AMTSubscriptExprBits.RBracketLoc = L;
}

SourceLocation getExprLoc() const LLVM_READONLY {
Expand Down Expand Up @@ -2741,7 +2741,7 @@ class MatrixSubscriptExpr : public Expr {
SubExprs[BASE] = Base;
SubExprs[ROW_IDX] = RowIdx;
SubExprs[COLUMN_IDX] = ColumnIdx;
ArrayOrMatrixSubscriptExprBits.RBracketLoc = RBracketLoc;
AMTSubscriptExprBits.RBracketLoc = RBracketLoc;
setDependence(computeDependence(this));
}

Expand Down Expand Up @@ -2782,10 +2782,10 @@ class MatrixSubscriptExpr : public Expr {
}

SourceLocation getRBracketLoc() const {
return ArrayOrMatrixSubscriptExprBits.RBracketLoc;
return AMTSubscriptExprBits.RBracketLoc;
}
void setRBracketLoc(SourceLocation L) {
ArrayOrMatrixSubscriptExprBits.RBracketLoc = L;
AMTSubscriptExprBits.RBracketLoc = L;
}

static bool classof(const Stmt *T) {
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/AST/Stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ class alignas(void *) Stmt {
unsigned IsType : 1; // true if operand is a type, false if an expression.
};

class ArrayOrMatrixSubscriptExprBitfields {
class AMTSubscriptExprBitfields {
friend class ArraySubscriptExpr;
friend class MatrixSubscriptExpr;

Expand Down Expand Up @@ -1034,7 +1034,7 @@ class alignas(void *) Stmt {
CharacterLiteralBitfields CharacterLiteralBits;
UnaryOperatorBitfields UnaryOperatorBits;
UnaryExprOrTypeTraitExprBitfields UnaryExprOrTypeTraitExprBits;
ArrayOrMatrixSubscriptExprBitfields ArrayOrMatrixSubscriptExprBits;
AMTSubscriptExprBitfields AMTSubscriptExprBits;
CallExprBitfields CallExprBits;
MemberExprBitfields MemberExprBits;
CastExprBitfields CastExprBits;
Expand Down
17 changes: 15 additions & 2 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,15 @@ class QualType {
/// Returns true if it is not a class or if the class might not be dynamic.
bool mayBeNotDynamicClass() const;

/// Returns true if it is a WebAssembly Reference Type.
bool isWebAssemblyReferenceType() const;

/// Returns true if it is a WebAssembly Externref Type.
bool isWebAssemblyExternrefType() const;

/// Returns true if it is a WebAssembly Funcref Type.
bool isWebAssemblyFuncrefType() const;

// Don't promise in the API that anything besides 'const' can be
// easily added.

Expand Down Expand Up @@ -2025,10 +2034,14 @@ class alignas(8) Type : public ExtQualsTypeCommonBase {
bool isSizelessType() const;
bool isSizelessBuiltinType() const;

/// Check if this is a WebAssembly Reference Type.
bool isWebAssemblyReferenceType() const;
/// Check if this is a WebAssembly Externref Type.
bool isWebAssemblyExternrefType() const;

/// Returns true if this is a WebAssembly table type: either an array of
/// reference types, or a pointer to a reference type (which can only be
/// created by array to pointer decay).
bool isWebAssemblyTableType() const;

/// Determines if this is a sizeless type supported by the
/// 'arm_sve_vector_bits' type attribute, which can be applied to a single
/// SVE vector or predicate, excluding tuple types such as svint32x4_t.
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -4102,3 +4102,11 @@ def WebAssemblyFuncref : TypeAttr, TargetSpecificAttr<TargetWebAssembly> {
let Documentation = [WebAssemblyExportNameDocs];
let Subjects = SubjectList<[TypedefName], ErrorDiag>;
}

def WasmTableType : TypeAttr {
let Spellings = [Clang<"wasm_table">];
let Subjects = SubjectList<[TypedefName], ErrorDiag>;
let Documentation = [Undocumented];
let ASTNode = 0;
let PragmaAttributeSupport = 0;
}
8 changes: 8 additions & 0 deletions clang/include/clang/Basic/BuiltinsWebAssembly.def
Original file line number Diff line number Diff line change
Expand Up @@ -201,5 +201,13 @@ TARGET_BUILTIN(__builtin_wasm_ref_null_extern, "i", "nct", "reference-types")
// return type.
TARGET_BUILTIN(__builtin_wasm_ref_null_func, "i", "nct", "reference-types")

// Table builtins
TARGET_BUILTIN(__builtin_wasm_table_set, "viii", "t", "reference-types")
TARGET_BUILTIN(__builtin_wasm_table_get, "iii", "t", "reference-types")
TARGET_BUILTIN(__builtin_wasm_table_size, "ii", "nt", "reference-types")
TARGET_BUILTIN(__builtin_wasm_table_grow, "iiii", "nt", "reference-types")
TARGET_BUILTIN(__builtin_wasm_table_fill, "viiii", "t", "reference-types")
TARGET_BUILTIN(__builtin_wasm_table_copy, "viiiii", "t", "reference-types")

#undef BUILTIN
#undef TARGET_BUILTIN
47 changes: 46 additions & 1 deletion clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -2170,6 +2170,8 @@ def err_reference_bind_to_vector_element : Error<
"%select{non-const|volatile}0 reference cannot bind to vector element">;
def err_reference_bind_to_matrix_element : Error<
"%select{non-const|volatile}0 reference cannot bind to matrix element">;
def err_reference_bind_to_table_element : Error<
"%select{non-const|volatile}0 reference cannot bind to table element">;
def err_reference_var_requires_init : Error<
"declaration of reference variable %0 requires an initializer">;
def err_reference_without_init : Error<
Expand Down Expand Up @@ -3029,6 +3031,7 @@ def err_attribute_invalid_bitint_vector_type : Error<
"'_BitInt' vector element width must be %select{a power of 2|"
"at least as wide as 'CHAR_BIT'}0">;
def err_attribute_invalid_matrix_type : Error<"invalid matrix element type %0">;
def err_attribute_invalid_wasm_table_type : Error<"invalid table element type %0">;
def err_attribute_bad_neon_vector_size : Error<
"Neon vector size must be 64 or 128 bits">;
def err_attribute_invalid_sve_type : Error<
Expand Down Expand Up @@ -6912,7 +6915,7 @@ def err_typecheck_sclass_func : Error<"illegal storage class on function">;
def err_static_block_func : Error<
"function declared in block scope cannot have 'static' storage class">;
def err_typecheck_address_of : Error<"address of %select{bit-field"
"|vector element|property expression|register variable|matrix element}0 requested">;
"|vector element|property expression|register variable|matrix element|table element}0 requested">;
def ext_typecheck_addrof_void : Extension<
"ISO C forbids taking the address of an expression of type 'void'">;
def err_unqualified_pointer_member_function : Error<
Expand Down Expand Up @@ -11602,8 +11605,12 @@ def err_builtin_invalid_arg_type: Error <
"floating point type|"
"vector of integers}1 (was %2)">;

def err_wasm_table_disabled: Error<
"WebAssembly table support is disabled. Pass -mreference-types to enable it">;
def err_builtin_matrix_disabled: Error<
"matrix types extension is disabled. Pass -fenable-matrix to enable it">;
def err_table_index_not_integer: Error<
"table index must be an integer">;
def err_matrix_index_not_integer: Error<
"matrix %select{row|column}0 index is not an integer">;
def err_matrix_index_outside_range: Error<
Expand Down Expand Up @@ -11741,4 +11748,42 @@ def err_wasm_reference_pr : Error<
"%select{pointers|references}0 to WebAssembly reference types are illegal">;
def err_wasm_ca_reference : Error<
"cannot %select{capture|take address of}0 WebAssembly reference">;
def err_wasm_addrof_table : Error<
"cannot take address of WebAssembly table">;
def err_wasm_table_pointer : Error<
"pointers to WebAssembly tables are illegal">;
def err_wasm_table_reference : Error<
"references to WebAssembly tables are illegal">;
def err_typecheck_wasm_table_must_have_zero_length : Error<
"only zero-length WebAssembly tables are currently supported">;
def err_wasm_table_in_function : Error<
"WebAssembly table cannot be declared within a function">;
def err_wasm_table_as_function_argument : Error<
"cannot use WebAssembly table as a function argument">;
def err_wasm_table_invalid_uett_operand : Error<
"invalid application of '%0' to WebAssembly table">;
def err_wasm_cast_table : Error<
"cannot cast WebAssembly table">;
def err_wasm_table_conditional_expression : Error<
"cannot use WebAssembly tables as the 2nd or 3rd operands of a conditional expression">;
def err_wasm_table_assignment : Error<
"cannot assign WebAssembly table to a variable">;
def err_wasm_table_return : Error<
"cannot return a WebAssembly table">;
def err_wasm_table_throw : Error<
"cannot throw a WebAssembly table">;
def err_wasm_table_catch : Error<
"cannot catch WebAssembly table">;
def err_wasm_table_exception_spec : Error<
"WebAssembly table not allowed in exception sepcification">;
def err_wasm_table_must_be_static : Error<
"WebAssembly table must be static">;
def err_wasm_multidimensional_ref_array : Error<
"multi-dimensional arrays of WebAssembly references are illegal">;
def err_wasm_builtin_arg_must_be_table_type : Error <
"%ordinal0 argument must be a WebAssembly table">;
def err_wasm_builtin_arg_must_match_table_element_type : Error <
"%ordinal0 argument must match the element type of the WebAssembly table in the %ordinal1 argument">;
def err_wasm_builtin_arg_must_be_integer_type : Error <
"%ordinal0 argument must be an integer">;
} // end of sema component.
5 changes: 4 additions & 1 deletion clang/include/clang/Basic/Specifiers.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,10 @@ namespace clang {
OK_ObjCSubscript,

/// A matrix component is a single element of a matrix.
OK_MatrixComponent
OK_MatrixComponent,

/// A table component is a single element of a WebAssembly table.
OK_TableComponent,
};

/// The reason why a DeclRefExpr does not constitute an odr-use.
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -13455,6 +13455,12 @@ class Sema final {
// WebAssembly builtin handling.
bool BuiltinWasmRefNullExtern(CallExpr *TheCall);
bool BuiltinWasmRefNullFunc(CallExpr *TheCall);
bool BuiltinWasmTableGet(CallExpr *TheCall);
bool BuiltinWasmTableSet(CallExpr *TheCall);
bool BuiltinWasmTableSize(CallExpr *TheCall);
bool BuiltinWasmTableGrow(CallExpr *TheCall);
bool BuiltinWasmTableFill(CallExpr *TheCall);
bool BuiltinWasmTableCopy(CallExpr *TheCall);

public:
enum FormatStringType {
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1645,7 +1645,7 @@ enum StmtCode {

/// An MatrixSubscriptExpr record.
EXPR_MATRIX_SUBSCRIPT,

/// A CallExpr record.
EXPR_CALL,

Expand Down
1 change: 0 additions & 1 deletion clang/include/clang/Serialization/TypeBitCodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,4 @@ TYPE_BIT_CODE(ConstantMatrix, CONSTANT_MATRIX, 52)
TYPE_BIT_CODE(DependentSizedMatrix, DEPENDENT_SIZE_MATRIX, 53)
TYPE_BIT_CODE(Using, USING, 54)
TYPE_BIT_CODE(BTFTagAttributed, BTFTAG_ATTRIBUTED, 55)

#undef TYPE_BIT_CODE
3 changes: 3 additions & 0 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ void TextNodeDumper::Visit(const Stmt *Node) {
case OK_MatrixComponent:
OS << " matrixcomponent";
break;
case OK_TableComponent:
OS << " tablecomponent";
break;
}
}
}
Expand Down
26 changes: 22 additions & 4 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2323,16 +2323,22 @@ bool Type::isSizelessBuiltinType() const {
return false;
}

bool Type::isWebAssemblyReferenceType() const {
return isWebAssemblyExternrefType();
}

bool Type::isWebAssemblyExternrefType() const {
if (const auto *BT = getAs<BuiltinType>())
return BT->getKind() == BuiltinType::WasmExternRef;
return false;
}

bool Type::isWebAssemblyTableType() const {
if (const auto *ATy = dyn_cast<ArrayType>(this)) {
return ATy->getElementType().isWebAssemblyReferenceType();
}
if (const auto *PTy = dyn_cast<PointerType>(this)) {
return PTy->getPointeeType().isWebAssemblyReferenceType();
}
return false;
}

bool Type::isSizelessType() const { return isSizelessBuiltinType(); }

bool Type::isVLSTBuiltinType() const {
Expand Down Expand Up @@ -2557,6 +2563,18 @@ bool QualType::hasNonTrivialToPrimitiveCopyCUnion(const RecordDecl *RD) {
return RD->hasNonTrivialToPrimitiveCopyCUnion();
}

bool QualType::isWebAssemblyReferenceType() const {
return isWebAssemblyExternrefType() || isWebAssemblyFuncrefType();
}

bool QualType::isWebAssemblyExternrefType() const {
return getTypePtr()->isWebAssemblyExternrefType();
}

bool QualType::isWebAssemblyFuncrefType() const {
return getTypePtr()->isFunctionPointerType() && getAddressSpace() == LangAS::wasm_funcref;
}

QualType::PrimitiveDefaultInitializeKind
QualType::isNonTrivialToPrimitiveDefaultInitialize() const {
if (const auto *RT =
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/WebAssembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ bool WebAssemblyTargetInfo::initFeatureMap(
Features["atomics"] = true;
Features["mutable-globals"] = true;
Features["tail-call"] = true;
Features["reference-types"] = true;
setSIMDLevel(Features, SIMD128, true);
} else if (CPU == "generic") {
Features["sign-ext"] = true;
Expand Down
Loading

0 comments on commit 8e3d6dd

Please sign in to comment.