-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[type] [refactor] Add compute_type for CustomIntType #2047
Merged
+184
−48
Merged
Changes from 17 commits
Commits
Show all changes
32 commits
Select commit
Hold shift + click to select a range
41b9965
rebase code from upstream
Hanke98 0b8fd8b
add llvm_ptr_type and data type bits
Hanke98 b1b5e56
add some comments
Hanke98 100ea35
[skip ci] enforce code format
taichi-gardener 3399981
use type factory
Hanke98 e98f450
[skip ci] enforce code format
taichi-gardener 9ff8476
update runtime
Hanke98 04cb2f3
[skip ci] enforce code format
taichi-gardener 15ffdfa
modify bit_ptr struct and rebase
Hanke98 a44bd21
[skip ci] enforce code format
taichi-gardener 6d82d39
fix bit_array
Hanke98 fab966e
use runtime to do global loading
Hanke98 7bfbcb5
[skip ci] enforce code format
taichi-gardener 1f9e511
add tests
Hanke98 9b109f5
[skip ci] enforce code format
taichi-gardener 10cd722
add more tetst cases and rebase
Hanke98 45dabf8
[skip ci] enforce code format
taichi-gardener 9d99341
fix bit struct
Hanke98 f045ec1
set physical type for bit_array
Hanke98 e344ca0
[skip ci] enforce code format
taichi-gardener a20a0e8
modify test cases
Hanke98 18a6738
[skip ci] enforce code format
taichi-gardener b8c4d49
Apply suggestions from code review
Hanke98 a7acc57
fix type factory
Hanke98 704bbe7
change funtion name
Hanke98 5022a10
[skip ci] enforce code format
taichi-gardener c1bf0e6
Apply suggestions from code review
Hanke98 cc8878b
[skip ci] enforce code format
taichi-gardener a2d4196
modify APIs
Hanke98 c9993cf
[skip ci] enforce code format
taichi-gardener 29f68ad
update
Hanke98 985f35e
remove todo
Hanke98 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -328,7 +328,8 @@ void CodeGenLLVM::visit(UnaryOpStmt *stmt) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto from_size = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (from->is<CustomIntType>()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// TODO: replace 32 with a customizable type | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from_size = 32; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from_size = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
data_type_size(from->cast<CustomIntType>()->get_compute_type()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
from_size = data_type_size(from); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
yuanming-hu marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -618,6 +619,31 @@ llvm::Type *CodeGenLLVM::llvm_type(DataType dt) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
return nullptr; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm::Type *CodeGenLLVM::llvm_ptr_type(DataType dt) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (dt->is_primitive(PrimitiveTypeID::i8) || | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
dt->is_primitive(PrimitiveTypeID::u8)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return llvm::Type::getInt8PtrTy(*llvm_context); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (dt->is_primitive(PrimitiveTypeID::i16) || | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
dt->is_primitive(PrimitiveTypeID::u16)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return llvm::Type::getInt16PtrTy(*llvm_context); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (dt->is_primitive(PrimitiveTypeID::i32) || | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
dt->is_primitive(PrimitiveTypeID::u32)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return llvm::Type::getInt32PtrTy(*llvm_context); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (dt->is_primitive(PrimitiveTypeID::i64) || | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
dt->is_primitive(PrimitiveTypeID::u64)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return llvm::Type::getInt64PtrTy(*llvm_context); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (dt->is_primitive(PrimitiveTypeID::u1)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return llvm::Type::getInt1PtrTy(*llvm_context); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (dt->is_primitive(PrimitiveTypeID::f32)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return llvm::Type::getFloatPtrTy(*llvm_context); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (dt->is_primitive(PrimitiveTypeID::f64)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return llvm::Type::getDoublePtrTy(*llvm_context); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TI_NOT_IMPLEMENTED; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return nullptr; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void CodeGenLLVM::visit(TernaryOpStmt *stmt) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TI_ASSERT(stmt->op_type == TernaryOpType::select); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm_val[stmt] = builder->CreateSelect( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -907,8 +933,8 @@ void CodeGenLLVM::visit(KernelReturnStmt *stmt) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
TI_NOT_IMPLEMENTED | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto intermediate_bits = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (stmt->value->ret_type->is<CustomIntType>()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
intermediate_bits = 32; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (auto cit = stmt->value->ret_type->cast<CustomIntType>()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
intermediate_bits = data_type_bits(cit->get_compute_type()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
intermediate_bits = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tlctx->get_data_type(stmt->value->ret_type)->getPrimitiveSizeInBits(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1103,14 +1129,16 @@ void CodeGenLLVM::visit(GlobalStoreStmt *stmt) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto ptr_type = stmt->ptr->ret_type->as<PointerType>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (ptr_type->is_bit_pointer()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto cit = ptr_type->get_pointee_type()->as<CustomIntType>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm::Value *byte_ptr = nullptr, *bit_offset = nullptr; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
read_bit_pointer(llvm_val[stmt->ptr], byte_ptr, bit_offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm::Value *byte_ptr = nullptr, *bit_offset = nullptr, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*physical_type_size = nullptr; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
read_bit_pointer(llvm_val[stmt->ptr], byte_ptr, bit_offset, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
physical_type_size); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
builder->CreateCall( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
get_runtime_function("set_partial_bits_b32"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
get_runtime_function("set_partial_bits"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{builder->CreateBitCast(byte_ptr, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm::Type::getInt32PtrTy(*llvm_context)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bit_offset, tlctx->get_constant(cit->get_num_bits()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm_val[stmt->data]}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm_val[stmt->data], physical_type_size}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
builder->CreateStore(llvm_val[stmt->data], llvm_val[stmt->ptr]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1122,25 +1150,16 @@ void CodeGenLLVM::visit(GlobalLoadStmt *stmt) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (stmt->ptr->ret_type->as<PointerType>()->is_bit_pointer()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto cit = stmt->ret_type->as<CustomIntType>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// 1. load bit pointer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm::Value *byte_ptr, *bit_offset; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
read_bit_pointer(llvm_val[stmt->ptr], byte_ptr, bit_offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto bit_level_container = builder->CreateLoad(builder->CreateBitCast( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
byte_ptr, llvm::Type::getInt32PtrTy(*llvm_context))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// 2. bit shifting | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// first left shift `32 - (offset + num_bits)` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// then right shift `32 - num_bits` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto bit_end = builder->CreateAdd(bit_offset, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tlctx->get_constant(cit->get_num_bits())); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto left = builder->CreateSub(tlctx->get_constant(32), bit_end); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto right = builder->CreateAdd(tlctx->get_constant(32), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tlctx->get_constant(-cit->get_num_bits())); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto step1 = builder->CreateShl(bit_level_container, left); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm::Value *step2 = nullptr; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (cit->get_is_signed()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
step2 = builder->CreateAShr(step1, right); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
step2 = builder->CreateLShr(step1, right); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm_val[stmt] = step2; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm::Value *byte_ptr, *bit_offset, *physical_type_size; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
read_bit_pointer(llvm_val[stmt->ptr], byte_ptr, bit_offset, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
physical_type_size); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto tmp = builder->CreateCall( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
get_runtime_function("load_partial_bits"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{byte_ptr, bit_offset, tlctx->get_constant(cit->get_num_bits()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
physical_type_size, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tlctx->get_constant((uint32)cit->get_is_signed())}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm_val[stmt] = builder->CreateIntCast( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tmp, llvm_type(cit->get_compute_type()), cit->get_is_signed()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm_val[stmt] = builder->CreateLoad(tlctx->get_data_type(stmt->ret_type), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm_val[stmt->ptr]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1236,14 +1255,17 @@ void CodeGenLLVM::visit(LinearizeStmt *stmt) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
void CodeGenLLVM::visit(IntegerOffsetStmt *stmt){TI_NOT_IMPLEMENTED} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm::Value *CodeGenLLVM::create_bit_ptr_struct(llvm::Value *byte_ptr_base, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm::Value *bit_offset) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm::Value *bit_offset, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int num_bits) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// 1. create a bit pointer struct | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// struct bit_pointer { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// i8* byte_ptr; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// i32 offset; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// i32 physical_type_size; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto struct_type = llvm::StructType::get( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
*llvm_context, {llvm::Type::getInt8PtrTy(*llvm_context), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm::Type::getInt32Ty(*llvm_context), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm::Type::getInt32Ty(*llvm_context)}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// 2. alloca the bit pointer struct | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto bit_ptr_struct = create_entry_block_alloca(struct_type); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1257,6 +1279,11 @@ llvm::Value *CodeGenLLVM::create_bit_ptr_struct(llvm::Value *byte_ptr_base, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
builder->CreateStore( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
bit_offset, builder->CreateGEP(bit_ptr_struct, {tlctx->get_constant(0), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tlctx->get_constant(1)})); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// 5. store `physical_type` in `bit_ptr_struct` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
builder->CreateStore( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tlctx->get_constant(num_bits), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
builder->CreateGEP(bit_ptr_struct, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{tlctx->get_constant(0), tlctx->get_constant(2)})); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return bit_ptr_struct; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1284,7 +1311,10 @@ void CodeGenLLVM::visit(SNodeLookupStmt *stmt) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
snode->dt.get_ptr()->as<BitArrayType>()->get_element_num_bits(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto offset = tlctx->get_constant(element_num_bits); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
offset = builder->CreateMul(offset, llvm_val[stmt->input_index]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm_val[stmt] = create_bit_ptr_struct(llvm_val[stmt->input_snode], offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm_val[stmt] = create_bit_ptr_struct( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm_val[stmt->input_snode], offset, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
data_type_bits( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
snode->dt.get_ptr()->as<BitArrayType>()->get_physical_type())); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TI_INFO(snode_type_name(snode->type)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TI_NOT_IMPLEMENTED | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -1299,7 +1329,9 @@ void CodeGenLLVM::visit(GetChStmt *stmt) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto bit_offset = bit_struct->get_member_bit_offset( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
stmt->input_snode->child_id(stmt->output_snode)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto offset = tlctx->get_constant(bit_offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm_val[stmt] = create_bit_ptr_struct(llvm_val[stmt->input_ptr], offset); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm_val[stmt] = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
create_bit_ptr_struct(llvm_val[stmt->input_ptr], offset, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
data_type_bits(bit_struct->get_physical_type())); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
auto ch = create_call(stmt->output_snode->get_ch_from_parent_func_name(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{builder->CreateBitCast( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove TODO here