Skip to content

Commit 216e46d

Browse files
committed
Compute stack slots for primitive types
1 parent 52657fb commit 216e46d

File tree

4 files changed

+59
-9
lines changed

4 files changed

+59
-9
lines changed

Diff for: libsolidity/experimental/analysis/TypeInference.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,7 @@ bool TypeInference::visit(TypeDefinition const& _typeDefinition)
807807
{
808808
members->second.emplace("abs", TypeMember{helper.functionType(*underlyingType, definedType)});
809809
members->second.emplace("rep", TypeMember{helper.functionType(definedType, *underlyingType)});
810+
annotation().underlyingTypes[constructor] = *underlyingType;
810811
}
811812

812813
if (helper.isPrimitiveType(definedType, PrimitiveType::Pair))

Diff for: libsolidity/experimental/analysis/TypeInference.h

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class TypeInference: public ASTConstVisitor
5050
std::map<TypeClass, std::map<std::string, Type>> typeClassFunctions;
5151
std::map<Token, std::tuple<TypeClass, std::string>> operators;
5252
std::map<TypeConstructor, std::map<std::string, TypeMember>> members;
53+
std::map<TypeConstructor, Type> underlyingTypes;
5354
};
5455
bool visit(Block const&) override { return true; }
5556
bool visit(VariableDeclarationStatement const&) override { return true; }

Diff for: libsolidity/experimental/codegen/IRGeneratorForStatements.cpp

+4-6
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ bool IRGeneratorForStatements::visit(TupleExpression const& _tupleExpression)
119119
{
120120
solUnimplementedAssert(component);
121121
component->accept(*this);
122-
components.emplace_back(var(*component).name());
122+
components.emplace_back(var(*component).commaSeparatedList());
123123
}
124124

125125
solUnimplementedAssert(false, "No support for tuples.");
@@ -205,7 +205,6 @@ void IRGeneratorForStatements::endVisit(BinaryOperation const& _binaryOperation)
205205
// TODO: get around resolveRecursive by passing the environment further down?
206206
functionType = m_context.env->resolveRecursive(functionType);
207207
m_context.enqueueFunctionDefinition(&functionDefinition, functionType);
208-
// TODO: account for return stack size
209208
m_code << "let " << var(_binaryOperation).commaSeparatedList() <<
210209
" := " << IRNames::function(*m_context.env, functionDefinition, functionType) << "(" <<
211210
var(_binaryOperation.leftExpression()).commaSeparatedList() <<
@@ -342,14 +341,13 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
342341
// TODO: get around resolveRecursive by passing the environment further down?
343342
functionType = m_context.env->resolveRecursive(functionType);
344343
m_context.enqueueFunctionDefinition(functionDefinition, functionType);
345-
// TODO: account for return stack size
346-
m_code << "let " << var(_functionCall).name() << " := " << IRNames::function(*m_context.env, *functionDefinition, functionType) << "(";
344+
m_code << "let " << var(_functionCall).commaSeparatedList() << " := " << IRNames::function(*m_context.env, *functionDefinition, functionType) << "(";
347345
auto const& arguments = _functionCall.arguments();
348346
if (arguments.size() > 1)
349347
for (auto arg: arguments | ranges::views::drop_last(1))
350-
m_code << var(*arg).name() << ", ";
348+
m_code << var(*arg).commaSeparatedList();
351349
if (!arguments.empty())
352-
m_code << var(*arguments.back()).name();
350+
m_code << var(*arguments.back()).commaSeparatedListPrefixed();
353351
m_code << ")\n";
354352
}
355353

Diff for: libsolidity/experimental/codegen/IRGeneratorForStatements.h

+53-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
#include <libsolidity/experimental/codegen/IRGenerationContext.h>
2222
#include <libsolidity/experimental/codegen/IRVariable.h>
23+
#include <libsolidity/experimental/ast/TypeSystemHelper.h>
24+
#include <libsolidity/experimental/analysis/TypeInference.h>
2325

2426
#include <libsolidity/ast/ASTVisitor.h>
2527

@@ -37,10 +39,58 @@ class IRGeneratorForStatements: public ASTConstVisitor
3739

3840
std::string generate(ASTNode const& _node);
3941

40-
static std::size_t stackSize(IRGenerationContext, Type)
42+
static std::size_t stackSize(IRGenerationContext const& _context, Type _type)
4143
{
42-
// TODO
43-
return 1;
44+
TypeSystemHelpers helper{_context.analysis.typeSystem()};
45+
_type = _context.env->resolve(_type);
46+
solAssert(std::holds_alternative<TypeConstant>(_type), "No monomorphized type.");
47+
48+
// type -> # stack slots
49+
// unit, itself -> 0
50+
// void, literals(integer), typeFunction -> error (maybe generate a revert)
51+
// word, bool, function -> 1
52+
// pair -> sum(stackSize(args))
53+
// user-defined -> stackSize(underlying type)
54+
TypeConstant typeConstant = std::get<TypeConstant>(_type);
55+
if (helper.isPrimitiveType(_type, PrimitiveType::Unit) ||
56+
helper.isPrimitiveType(_type, PrimitiveType::Itself))
57+
return 0;
58+
else if (helper.isPrimitiveType(_type, PrimitiveType::Bool) || helper.isPrimitiveType(_type, PrimitiveType::Word))
59+
{
60+
solAssert(typeConstant.arguments.empty(), "Primitive type Bool or Word should have no arguments.");
61+
return 1;
62+
}
63+
else if (helper.isFunctionType(_type))
64+
return 1;
65+
else if (
66+
helper.isPrimitiveType(_type, PrimitiveType::Integer) ||
67+
helper.isPrimitiveType(_type, PrimitiveType::Void) ||
68+
helper.isPrimitiveType(_type, PrimitiveType::TypeFunction))
69+
solThrow(langutil::CompilerError, "Primitive type Void, Unit or TypeFunction do not have stack slot"); // FIXME: proper error
70+
else if (helper.isPrimitiveType(_type, PrimitiveType::Pair))
71+
{
72+
solAssert(typeConstant.arguments.size() == 2);
73+
return stackSize(_context, typeConstant.arguments.front()) + stackSize(_context, typeConstant.arguments.back());
74+
}
75+
else
76+
{
77+
Type underlyingType = _context.analysis.annotation<TypeInference>().underlyingTypes.at(typeConstant.constructor);
78+
if (helper.isTypeConstant(underlyingType))
79+
return stackSize(_context, underlyingType);
80+
81+
TypeEnvironment env = _context.env->clone();
82+
Type genericFunctionType = helper.typeFunctionType(
83+
helper.tupleType(typeConstant.arguments),
84+
env.typeSystem().freshTypeVariable({}));
85+
solAssert(env.unify(genericFunctionType, underlyingType).empty());
86+
87+
Type resolvedType = env.resolveRecursive(genericFunctionType);
88+
auto [argumentType, resultType] = helper.destTypeFunctionType(resolvedType);
89+
return stackSize(_context, resultType);
90+
}
91+
92+
//TODO: sum types
93+
return 0;
4494
}
4595

4696
private:

0 commit comments

Comments
 (0)