Signed and unsinged int variants
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
@extern putchar fun: character sint32 -> sint32
|
||||
//@extern putchar fun: character sint32 -> sint32
|
||||
|
||||
// ./build/brb samples/test.brc -S -x86-asm-syntax=intel
|
||||
|
||||
@@ -28,10 +28,10 @@ i u32 <- 0, rep text[i] != 0:
|
||||
ret num1 + num2
|
||||
;*/
|
||||
|
||||
rawAdd raw<"=r,r,r">: num1 sint32, num2 sint32 -> sint32
|
||||
/*rawAdd raw<"=r,r,r">: num1 sint32, num2 sint32 -> sint32
|
||||
add $1, $2
|
||||
mov $0, $1
|
||||
;
|
||||
;*/
|
||||
|
||||
/*rawAdd raw: num1 sint32, num2 sint32 -> sint32
|
||||
add $1, $2
|
||||
@@ -48,13 +48,12 @@ rawAdd raw<"=r,r,r">: num1 sint32, num2 sint32 -> sint32
|
||||
|
||||
;*/
|
||||
|
||||
main fun -> sint32
|
||||
/*a sint32 <- 4
|
||||
b sint32 <- 5
|
||||
|
||||
res sint32 <- rawAdd(4, 5)*/
|
||||
putchar('@')
|
||||
putchar('\n')
|
||||
main fun -> u32
|
||||
num1 u8 <- 42
|
||||
num2 s8 <- 15
|
||||
num3 u32 <- 1234123
|
||||
num4 s32 <- 345345
|
||||
num5 r32 <- 42.58
|
||||
|
||||
ret 0
|
||||
;
|
||||
@@ -32,8 +32,11 @@ moduleName(moduleName), sourceFileName(sourceFileName), statements(statements) {
|
||||
|
||||
typeVoid = llvm::Type::getVoidTy(*context);
|
||||
typeBool = llvm::Type::getInt1Ty(*context);
|
||||
typeSint32 = llvm::Type::getInt32Ty(*context);
|
||||
typeReal32 = llvm::Type::getFloatTy(*context);
|
||||
typeU8 = llvm::Type::getInt8Ty(*context);
|
||||
typeU32 = llvm::Type::getInt32Ty(*context);
|
||||
typeS8 = llvm::Type::getInt8Ty(*context);
|
||||
typeS32 = llvm::Type::getInt32Ty(*context);
|
||||
typeR32 = llvm::Type::getFloatTy(*context);
|
||||
}
|
||||
|
||||
shared_ptr<llvm::Module> ModuleBuilder::getModule() {
|
||||
@@ -325,10 +328,16 @@ llvm::Value *ModuleBuilder::valueForLiteral(shared_ptr<ExpressionLiteral> expres
|
||||
return llvm::UndefValue::get(typeVoid);
|
||||
case ValueTypeKind::BOOL:
|
||||
return llvm::ConstantInt::get(typeBool, expression->getBoolValue(), true);
|
||||
case ValueTypeKind::SINT32:
|
||||
return llvm::ConstantInt::get(typeSint32, expression->getSint32Value(), true);
|
||||
case ValueTypeKind::REAL32:
|
||||
return llvm::ConstantInt::get(typeReal32, expression->getReal32Value(), true);
|
||||
case ValueTypeKind::U8:
|
||||
return llvm::ConstantInt::get(typeU8, expression->getU8Value(), true);
|
||||
case ValueTypeKind::U32:
|
||||
return llvm::ConstantInt::get(typeU32, expression->getU32Value(), true);
|
||||
case ValueTypeKind::S8:
|
||||
return llvm::ConstantInt::get(typeS8, expression->getS8Value(), true);
|
||||
case ValueTypeKind::S32:
|
||||
return llvm::ConstantInt::get(typeS32, expression->getS32Value(), true);
|
||||
case ValueTypeKind::R32:
|
||||
return llvm::ConstantInt::get(typeR32, expression->getR32Value(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,9 +364,11 @@ llvm::Value *ModuleBuilder::valueForBinary(shared_ptr<ExpressionBinary> expressi
|
||||
|
||||
if (type == typeBool) {
|
||||
return valueForBinaryBool(expression->getOperation(), leftValue, rightValue);
|
||||
} else if (type == typeSint32 || type == typeVoid) {
|
||||
return valueForBinaryInteger(expression->getOperation(), leftValue, rightValue);
|
||||
} else if (type == typeReal32) {
|
||||
} else if (type == typeU8 || type == typeU32) {
|
||||
return valueForBinaryUnsignedInteger(expression->getOperation(), leftValue, rightValue);
|
||||
} else if (type == typeS8 || type == typeS32) {
|
||||
return valueForBinarySignedInteger(expression->getOperation(), leftValue, rightValue);
|
||||
} else if (type == typeR32) {
|
||||
return valueForBinaryReal(expression->getOperation(), leftValue, rightValue);
|
||||
}
|
||||
|
||||
@@ -377,30 +388,57 @@ llvm::Value *ModuleBuilder::valueForBinaryBool(ExpressionBinaryOperation operati
|
||||
}
|
||||
}
|
||||
|
||||
llvm::Value *ModuleBuilder::valueForBinaryInteger(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue) {
|
||||
llvm::Value *ModuleBuilder::valueForBinaryUnsignedInteger(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue) {
|
||||
switch (operation) {
|
||||
case ExpressionBinaryOperation::EQUAL:
|
||||
return builder->CreateICmpEQ(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::NOT_EQUAL:
|
||||
return builder->CreateICmpNE(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::LESS:
|
||||
return builder->CreateICmpSLT(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::LESS_EQUAL:
|
||||
return builder->CreateICmpSLE(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::GREATER:
|
||||
return builder->CreateICmpSGT(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::GREATER_EQUAL:
|
||||
return builder->CreateICmpSGE(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::ADD:
|
||||
return builder->CreateNSWAdd(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::SUB:
|
||||
return builder->CreateNSWSub(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::MUL:
|
||||
return builder->CreateNSWMul(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::DIV:
|
||||
return builder->CreateSDiv(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::MOD:
|
||||
return builder->CreateSRem(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::EQUAL:
|
||||
return builder->CreateICmpEQ(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::NOT_EQUAL:
|
||||
return builder->CreateICmpNE(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::LESS:
|
||||
return builder->CreateICmpSLT(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::LESS_EQUAL:
|
||||
return builder->CreateICmpSLE(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::GREATER:
|
||||
return builder->CreateICmpSGT(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::GREATER_EQUAL:
|
||||
return builder->CreateICmpSGE(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::ADD:
|
||||
return builder->CreateNUWAdd(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::SUB:
|
||||
return builder->CreateNUWSub(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::MUL:
|
||||
return builder->CreateNUWMul(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::DIV:
|
||||
return builder->CreateUDiv(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::MOD:
|
||||
return builder->CreateURem(leftValue, rightValue);
|
||||
}
|
||||
}
|
||||
|
||||
llvm::Value *ModuleBuilder::valueForBinarySignedInteger(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue) {
|
||||
switch (operation) {
|
||||
case ExpressionBinaryOperation::EQUAL:
|
||||
return builder->CreateICmpEQ(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::NOT_EQUAL:
|
||||
return builder->CreateICmpNE(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::LESS:
|
||||
return builder->CreateICmpSLT(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::LESS_EQUAL:
|
||||
return builder->CreateICmpSLE(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::GREATER:
|
||||
return builder->CreateICmpSGT(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::GREATER_EQUAL:
|
||||
return builder->CreateICmpSGE(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::ADD:
|
||||
return builder->CreateNSWAdd(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::SUB:
|
||||
return builder->CreateNSWSub(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::MUL:
|
||||
return builder->CreateNSWMul(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::DIV:
|
||||
return builder->CreateSDiv(leftValue, rightValue);
|
||||
case ExpressionBinaryOperation::MOD:
|
||||
return builder->CreateSRem(leftValue, rightValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -605,10 +643,16 @@ llvm::Type *ModuleBuilder::typeForValueType(shared_ptr<ValueType> valueType, int
|
||||
return typeVoid;
|
||||
case ValueTypeKind::BOOL:
|
||||
return typeBool;
|
||||
case ValueTypeKind::SINT32:
|
||||
return typeSint32;
|
||||
case ValueTypeKind::REAL32:
|
||||
return typeReal32;
|
||||
case ValueTypeKind::U8:
|
||||
return typeU8;
|
||||
case ValueTypeKind::U32:
|
||||
return typeU32;
|
||||
case ValueTypeKind::S8:
|
||||
return typeS8;
|
||||
case ValueTypeKind::S32:
|
||||
return typeS32;
|
||||
case ValueTypeKind::R32:
|
||||
return typeR32;
|
||||
case ValueTypeKind::DATA: {
|
||||
if (valueType->getSubType() == nullptr)
|
||||
return nullptr;
|
||||
|
||||
@@ -56,8 +56,11 @@ private:
|
||||
|
||||
llvm::Type *typeVoid;
|
||||
llvm::Type *typeBool;
|
||||
llvm::IntegerType *typeSint32;
|
||||
llvm::Type *typeReal32;
|
||||
llvm::IntegerType *typeU8;
|
||||
llvm::IntegerType *typeU32;
|
||||
llvm::IntegerType *typeS8;
|
||||
llvm::IntegerType *typeS32;
|
||||
llvm::Type *typeR32;
|
||||
|
||||
vector<shared_ptr<Statement>> statements;
|
||||
stack<Scope> scopes;
|
||||
@@ -80,7 +83,8 @@ private:
|
||||
llvm::Value *valueForGrouping(shared_ptr<ExpressionGrouping> expression);
|
||||
llvm::Value *valueForBinary(shared_ptr<ExpressionBinary> expression);
|
||||
llvm::Value *valueForBinaryBool(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue);
|
||||
llvm::Value *valueForBinaryInteger(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue);
|
||||
llvm::Value *valueForBinaryUnsignedInteger(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue);
|
||||
llvm::Value *valueForBinarySignedInteger(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue);
|
||||
llvm::Value *valueForBinaryReal(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue);
|
||||
llvm::Value *valueForIfElse(shared_ptr<ExpressionIfElse> expression);
|
||||
llvm::Value *valueForVar(shared_ptr<ExpressionVariable> expression);
|
||||
|
||||
@@ -207,10 +207,16 @@ string Logger::toString(shared_ptr<ValueType> valueType) {
|
||||
return "NONE";
|
||||
case ValueTypeKind::BOOL:
|
||||
return "BOOL";
|
||||
case ValueTypeKind::SINT32:
|
||||
return "SINT32";
|
||||
case ValueTypeKind::REAL32:
|
||||
return "REAL32";
|
||||
case ValueTypeKind::U8:
|
||||
return "U8";
|
||||
case ValueTypeKind::U32:
|
||||
return "U32";
|
||||
case ValueTypeKind::S8:
|
||||
return "S8";
|
||||
case ValueTypeKind::S32:
|
||||
return "S32";
|
||||
case ValueTypeKind::R32:
|
||||
return "R32";
|
||||
case ValueTypeKind::DATA:
|
||||
return "[]";
|
||||
}
|
||||
@@ -420,10 +426,16 @@ string Logger::toString(shared_ptr<ExpressionLiteral> expression) {
|
||||
return "NONE";
|
||||
case ValueTypeKind::BOOL:
|
||||
return expression->getBoolValue() ? "true" : "false";
|
||||
case ValueTypeKind::SINT32:
|
||||
return to_string(expression->getSint32Value());
|
||||
case ValueTypeKind::REAL32:
|
||||
return to_string(expression->getReal32Value());
|
||||
case ValueTypeKind::U8:
|
||||
return to_string(expression->getU8Value());
|
||||
case ValueTypeKind::U32:
|
||||
return to_string(expression->getU32Value());
|
||||
case ValueTypeKind::S8:
|
||||
return to_string(expression->getS8Value());
|
||||
case ValueTypeKind::S32:
|
||||
return to_string(expression->getS32Value());
|
||||
case ValueTypeKind::R32:
|
||||
return to_string(expression->getR32Value());
|
||||
default:
|
||||
return "?";
|
||||
}
|
||||
|
||||
@@ -15,14 +15,14 @@ shared_ptr<ExpressionLiteral> ExpressionLiteral::expressionLiteralForToken(share
|
||||
case TokenKind::INTEGER_DEC: {
|
||||
string numString = token->getLexme();
|
||||
erase(numString, '_');
|
||||
expression->sint32Value = stoi(numString, nullptr, 10);
|
||||
expression->s32Value = stoi(numString, nullptr, 10);
|
||||
expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
|
||||
break;
|
||||
}
|
||||
case TokenKind::INTEGER_HEX: {
|
||||
string numString = token->getLexme();
|
||||
erase(numString, '_');
|
||||
expression->sint32Value = stoi(numString, nullptr, 16);
|
||||
expression->u32Value = stoul(numString, nullptr, 16);
|
||||
expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
|
||||
break;
|
||||
}
|
||||
@@ -30,7 +30,7 @@ shared_ptr<ExpressionLiteral> ExpressionLiteral::expressionLiteralForToken(share
|
||||
string numString = token->getLexme();
|
||||
erase(numString, '_');
|
||||
numString = numString.substr(2, numString.size()-1);
|
||||
expression->sint32Value = stoi(numString, nullptr, 2);
|
||||
expression->u32Value = stoul(numString, nullptr, 2);
|
||||
expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
|
||||
break;
|
||||
}
|
||||
@@ -41,11 +41,11 @@ shared_ptr<ExpressionLiteral> ExpressionLiteral::expressionLiteralForToken(share
|
||||
return nullptr;
|
||||
|
||||
expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
|
||||
expression->sint32Value = *charValue;
|
||||
expression->u32Value = *charValue;
|
||||
return expression;
|
||||
}
|
||||
case TokenKind::REAL:
|
||||
expression->real32Value = stof(token->getLexme());
|
||||
expression->r32Value = stof(token->getLexme());
|
||||
expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
|
||||
break;
|
||||
default:
|
||||
@@ -62,10 +62,22 @@ bool ExpressionLiteral::getBoolValue() {
|
||||
return boolValue;
|
||||
}
|
||||
|
||||
int32_t ExpressionLiteral::getSint32Value() {
|
||||
return sint32Value;
|
||||
uint8_t ExpressionLiteral::getU8Value() {
|
||||
return s32Value;
|
||||
}
|
||||
|
||||
float ExpressionLiteral::getReal32Value() {
|
||||
return real32Value;
|
||||
uint32_t ExpressionLiteral::getU32Value() {
|
||||
return s32Value;
|
||||
}
|
||||
|
||||
int8_t ExpressionLiteral::getS8Value() {
|
||||
return s32Value;
|
||||
}
|
||||
|
||||
int32_t ExpressionLiteral::getS32Value() {
|
||||
return s32Value;
|
||||
}
|
||||
|
||||
float ExpressionLiteral::getR32Value() {
|
||||
return r32Value;
|
||||
}
|
||||
|
||||
@@ -6,16 +6,22 @@
|
||||
class ExpressionLiteral: public Expression {
|
||||
private:
|
||||
bool boolValue;
|
||||
int32_t sint32Value;
|
||||
float real32Value;
|
||||
uint8_t u8Value;
|
||||
uint32_t u32Value;
|
||||
int8_t s8Value;
|
||||
int32_t s32Value;
|
||||
float r32Value;
|
||||
|
||||
public:
|
||||
static shared_ptr<ExpressionLiteral> expressionLiteralForToken(shared_ptr<Token> token);
|
||||
|
||||
ExpressionLiteral();
|
||||
bool getBoolValue();
|
||||
int32_t getSint32Value();
|
||||
float getReal32Value();
|
||||
uint8_t getU8Value();
|
||||
uint32_t getU32Value();
|
||||
int8_t getS8Value();
|
||||
int32_t getS32Value();
|
||||
float getR32Value();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1052,7 +1052,7 @@ optional<ParseeResult> Parser::valueTypeParseeResult(int index) {
|
||||
int storedIndex = currentIndex;
|
||||
currentIndex = index;
|
||||
shared_ptr<Expression> expressionValue = matchExpressionLiteral();
|
||||
typeArg = dynamic_pointer_cast<ExpressionLiteral>(expressionValue)->getSint32Value();
|
||||
typeArg = dynamic_pointer_cast<ExpressionLiteral>(expressionValue)->getU32Value();
|
||||
currentIndex = storedIndex;
|
||||
index++;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,11 @@
|
||||
|
||||
shared_ptr<ValueType> ValueType::NONE = make_shared<ValueType>(ValueTypeKind::NONE, nullptr, 0);
|
||||
shared_ptr<ValueType> ValueType::BOOL = make_shared<ValueType>(ValueTypeKind::BOOL, nullptr, 0);
|
||||
shared_ptr<ValueType> ValueType::SINT32 = make_shared<ValueType>(ValueTypeKind::SINT32, nullptr, 0);
|
||||
shared_ptr<ValueType> ValueType::REAL32 = make_shared<ValueType>(ValueTypeKind::REAL32, nullptr, 0);
|
||||
shared_ptr<ValueType> ValueType::U8 = make_shared<ValueType>(ValueTypeKind::U8, nullptr, 0);
|
||||
shared_ptr<ValueType> ValueType::U32 = make_shared<ValueType>(ValueTypeKind::U32, nullptr, 0);
|
||||
shared_ptr<ValueType> ValueType::S8 = make_shared<ValueType>(ValueTypeKind::S8, nullptr, 0);
|
||||
shared_ptr<ValueType> ValueType::S32 = make_shared<ValueType>(ValueTypeKind::S32, nullptr, 0);
|
||||
shared_ptr<ValueType> ValueType::R32 = make_shared<ValueType>(ValueTypeKind::R32, nullptr, 0);
|
||||
|
||||
ValueType::ValueType(ValueTypeKind kind, shared_ptr<ValueType> subType, int valueArg):
|
||||
kind(kind), subType(subType), valueArg(valueArg) { }
|
||||
@@ -16,10 +19,16 @@ shared_ptr<ValueType> ValueType::valueTypeForToken(shared_ptr<Token> token, shar
|
||||
string lexme = token->getLexme();
|
||||
if (lexme.compare("bool") == 0)
|
||||
return make_shared<ValueType>(ValueTypeKind::BOOL, subType, valueArg);
|
||||
else if (lexme.compare("sint32") == 0)
|
||||
return make_shared<ValueType>(ValueTypeKind::SINT32, subType, valueArg);
|
||||
else if (lexme.compare("real32") == 0)
|
||||
return make_shared<ValueType>(ValueTypeKind::REAL32, subType, valueArg);
|
||||
else if (lexme.compare("u8") == 0)
|
||||
return make_shared<ValueType>(ValueTypeKind::U8, subType, valueArg);
|
||||
else if (lexme.compare("u32") == 0)
|
||||
return make_shared<ValueType>(ValueTypeKind::U32, subType, valueArg);
|
||||
else if (lexme.compare("s8") == 0)
|
||||
return make_shared<ValueType>(ValueTypeKind::S8, subType, valueArg);
|
||||
else if (lexme.compare("s32") == 0)
|
||||
return make_shared<ValueType>(ValueTypeKind::S32, subType, valueArg);
|
||||
else if (lexme.compare("r32") == 0)
|
||||
return make_shared<ValueType>(ValueTypeKind::R32, subType, valueArg);
|
||||
else if (lexme.compare("data") == 0)
|
||||
return make_shared<ValueType>(ValueTypeKind::DATA, subType, valueArg);
|
||||
else
|
||||
@@ -31,9 +40,9 @@ shared_ptr<ValueType> ValueType::valueTypeForToken(shared_ptr<Token> token, shar
|
||||
case TokenKind::INTEGER_HEX:
|
||||
case TokenKind::INTEGER_BIN:
|
||||
case TokenKind::INTEGER_CHAR:
|
||||
return make_shared<ValueType>(ValueTypeKind::SINT32, nullptr, 0);
|
||||
return make_shared<ValueType>(ValueTypeKind::U32, nullptr, 0);
|
||||
case TokenKind::REAL:
|
||||
return make_shared<ValueType>(ValueTypeKind::REAL32, nullptr, 0);
|
||||
return make_shared<ValueType>(ValueTypeKind::R32, nullptr, 0);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -10,8 +10,11 @@ using namespace std;
|
||||
enum class ValueTypeKind {
|
||||
NONE,
|
||||
BOOL,
|
||||
SINT32,
|
||||
REAL32,
|
||||
U8,
|
||||
U32,
|
||||
S8,
|
||||
S32,
|
||||
R32,
|
||||
DATA
|
||||
};
|
||||
|
||||
@@ -24,8 +27,11 @@ private:
|
||||
public:
|
||||
static shared_ptr<ValueType> NONE;
|
||||
static shared_ptr<ValueType> BOOL;
|
||||
static shared_ptr<ValueType> SINT32;
|
||||
static shared_ptr<ValueType> REAL32;
|
||||
static shared_ptr<ValueType> U8;
|
||||
static shared_ptr<ValueType> U32;
|
||||
static shared_ptr<ValueType> S8;
|
||||
static shared_ptr<ValueType> S32;
|
||||
static shared_ptr<ValueType> R32;
|
||||
static shared_ptr<ValueType> valueTypeForToken(shared_ptr<Token> token, shared_ptr<ValueType> subType, int valueArg);
|
||||
|
||||
ValueType(ValueTypeKind kind, shared_ptr<ValueType> subType, int valueArg);
|
||||
|
||||
Reference in New Issue
Block a user