Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | codegen: improved the translation of address computations into llvm GEP instructions |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | cir-stack-language |
| Files: | files | file ages | folders |
| SHA3-256: |
2a03dd67e58879fa73ad80eb1142ae85 |
| User & Date: | zlodo 2022-06-28 22:23:50.963 |
Context
|
2022-06-28
| ||
| 22:51 | Removed an unusued file and a left over debugging profanity check-in: 6c5b747f5c user: zlodo tags: cir-stack-language | |
| 22:23 | codegen: improved the translation of address computations into llvm GEP instructions check-in: 2a03dd67e5 user: zlodo tags: cir-stack-language | |
|
2022-06-27
| ||
| 16:56 |
| |
Changes
Changes to bs/codegen/address.cpp.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include "codegen.h"
#include "builtins/builtins.h"
using namespace goose;
using namespace goose::codegen;
using namespace goose::builtins;
bool Module::buildInstruction( State& st, const VarAddr& va )
{
auto* ppVal = st.temporaries->get( va.varIndex() );
assert( ppVal );
if( !ppVal )
return false;
| > > > > > > > > > > > > > > | | | | < < < < < < < < < < < < | < | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
#include "codegen.h"
#include "builtins/builtins.h"
using namespace goose;
using namespace goose::codegen;
using namespace goose::builtins;
llvm::Value* codegen::AddressToGEP( llvm::IRBuilder<>& builder, const codegen::Address& addr )
{
if( addr.path().empty() )
return addr.originAddr();
llvm::SmallVector< llvm::Value*, 8 > idxs;
idxs.push_back( llvm::ConstantInt::get( llvm::Type::getInt32Ty( GetLLVMContext() ), 0 ) );
for( auto it = addr.path().rbegin(); it != addr.path().rend(); ++it )
idxs.push_back( llvm::ConstantInt::get( llvm::Type::getInt32Ty( GetLLVMContext() ), *it ) );
return builder.CreateGEP( addr.originAddr()->getType()->getScalarType()->getPointerElementType(), addr.originAddr(), idxs );
}
bool Module::buildInstruction( State& st, const VarAddr& va )
{
auto* ppVal = st.temporaries->get( va.varIndex() );
assert( ppVal );
if( !ppVal )
return false;
st.stack.push( Address( *ppVal ) );
return true;
}
bool Module::buildInstruction( State& st, const TempAddr& ta )
{
auto initVal = st.stack.pop( m_llvmBuilder );
if( !initVal )
return false;
auto* ppVal = st.temporaries->get( ta.tempIndex() );
if( !ppVal )
{
st.temporaries->set( ta.tempIndex(), *initVal );
ppVal = st.temporaries->get( ta.tempIndex() );
}
if( llvm::isa< llvm::AllocaInst >( **ppVal ) )
{
st.stack.push( Address( *ppVal ) );
return true;
}
auto* pAlloca = buildAlloca( st, ( *ppVal )->getType() );
m_llvmBuilder.CreateStore( *ppVal, pAlloca );
st.temporaries->set( ta.tempIndex(), pAlloca );
st.stack.push( Address( pAlloca ) );
return true;
}
bool Module::buildInstruction( State& st, const Select& s )
{
auto baseAddr = st.stack.pop();
if( !baseAddr )
return false;
if( holds_alternative< Address >( *baseAddr ) )
st.stack.push( Address::Select( move( get< Address >( *baseAddr ) ), s.memberIndex() ) );
else
st.stack.push( Address::Select( Address( get< llvm::Value* >( *baseAddr ) ), s.memberIndex() ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::GhostCall& gc )
{
// We should never encounter this during codegen, since it's a construct only
// intended to be used in verification expressions.
|
| ︙ | ︙ |
Added bs/codegen/address.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#ifndef GOOSE_CODEGEN_ADDRESS_H
#define GOOSE_CODEGEN_ADDRESS_H
namespace goose::codegen
{
class Address
{
public:
Address( llvm::Value* originAddr ) :
m_originAddr( originAddr )
{}
auto originAddr() const { return m_originAddr; }
const auto& path() const { return m_path; }
static Address Select( Address&& baseAddr, uint32_t index )
{
baseAddr.m_path.emplace_back( index );
return baseAddr;
}
private:
SelectPath m_path;
llvm::Value* m_originAddr = nullptr;
};
extern llvm::Value* AddressToGEP( llvm::IRBuilder<>& builder, const codegen::Address& addr );
}
#endif
|
Changes to bs/codegen/arithops.cpp.
1 2 3 4 5 6 7 8 9 |
#include "codegen.h"
#include "builtins/builtins.h"
using namespace goose;
using namespace goose::codegen;
using namespace goose::builtins;
bool Module::buildInstruction( State& st, const cir::Add& bo )
{
| | | | | | | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
#include "codegen.h"
#include "builtins/builtins.h"
using namespace goose;
using namespace goose::codegen;
using namespace goose::builtins;
bool Module::buildInstruction( State& st, const cir::Add& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateAdd( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::Sub& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateSub( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::Mul& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateMul( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::UDiv& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateUDiv( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::SDiv& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateSDiv( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::URem& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateURem( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::SRem& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateSRem( *lhs, *rhs ) );
return true;
}
|
Changes to bs/codegen/basicblock.cpp.
| ︙ | ︙ | |||
68 69 70 71 72 73 74 |
{
m_llvmBuilder.CreateRetVoid();
return true;
}
bool Module::buildTerminator( State& st, const cir::Ret& r )
{
| | | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
{
m_llvmBuilder.CreateRetVoid();
return true;
}
bool Module::buildTerminator( State& st, const cir::Ret& r )
{
auto retVal = st.stack.pop( m_llvmBuilder );
if( !retVal )
return false;
m_llvmBuilder.CreateRet( *retVal );
return true;
}
|
| ︙ | ︙ | |||
91 92 93 94 95 96 97 |
return false;
return true;
}
bool Module::buildTerminator( State& st, const cir::CondBranch& cb )
{
| | | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
return false;
return true;
}
bool Module::buildTerminator( State& st, const cir::CondBranch& cb )
{
auto condVal = st.stack.pop( m_llvmBuilder );
if( !condVal )
return false;
auto pTrueLLVMBB = GetOrCreateLLVMBB( st, cb.trueDest().lock() );
auto pFalseLLVMBB = GetOrCreateLLVMBB( st, cb.falseDest().lock() );
m_llvmBuilder.CreateCondBr( *condVal, pTrueLLVMBB, pFalseLLVMBB );
|
| ︙ | ︙ |
Changes to bs/codegen/codegen.h.
| ︙ | ︙ | |||
23 24 25 26 27 28 29 30 31 32 33 |
using namespace cir;
using namespace sema;
extern llvm::LLVMContext& GetLLVMContext();
extern optional< string > Mangle( const Term& identity );
}
#include "stack.h"
#include "module.h"
#endif
| > | 23 24 25 26 27 28 29 30 31 32 33 34 |
using namespace cir;
using namespace sema;
extern llvm::LLVMContext& GetLLVMContext();
extern optional< string > Mangle( const Term& identity );
}
#include "address.h"
#include "stack.h"
#include "module.h"
#endif
|
Changes to bs/codegen/compareops.cpp.
1 2 3 4 5 6 7 8 9 |
#include "codegen.h"
#include "builtins/builtins.h"
using namespace goose;
using namespace goose::codegen;
using namespace goose::builtins;
bool Module::buildInstruction( State& st, const cir::Eq& bo )
{
| | | | | | | | | | | | | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
#include "codegen.h"
#include "builtins/builtins.h"
using namespace goose;
using namespace goose::codegen;
using namespace goose::builtins;
bool Module::buildInstruction( State& st, const cir::Eq& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateICmpEQ( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::Neq& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateICmpNE( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::UGT& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateICmpUGT( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::UGE& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateICmpUGE( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::ULT& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateICmpULT( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::ULE& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateICmpULE( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::SGT& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateICmpSGT( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::SGE& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateICmpSGE( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::SLT& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateICmpSLT( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::SLE& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateICmpSLE( *lhs, *rhs ) );
return true;
}
|
Changes to bs/codegen/instructions.cpp.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 |
bool Module::buildInstruction( State& st, const monostate& )
{
return false;
}
bool Module::buildInstruction( State& st, const cir::Call& call )
{
| | | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
bool Module::buildInstruction( State& st, const monostate& )
{
return false;
}
bool Module::buildInstruction( State& st, const cir::Call& call )
{
auto callee = st.stack.pop< llvm::Function* >( m_llvmBuilder );
if( !callee )
return false;
llvm::SmallVector< llvm::Value*, 8 > args;
args.resize( call.numArgs() );
for( uint32_t i = 0; i < call.numArgs(); ++i )
{
auto parg = st.stack.pop( m_llvmBuilder );
if( !parg )
return false;
args[call.numArgs() - i - 1] = *parg;
}
st.stack.push( m_llvmBuilder.CreateCall( llvm::FunctionCallee( *callee ), args ) );
|
| ︙ | ︙ | |||
59 60 61 62 63 64 65 |
st.stack.push( val );
return true;
}
bool Module::buildInstruction( State& st, const cir::CreateTemporary& ct )
{
| | | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
st.stack.push( val );
return true;
}
bool Module::buildInstruction( State& st, const cir::CreateTemporary& ct )
{
auto initVal = st.stack.pop( m_llvmBuilder );
if( !initVal )
return false;
createTemporary( st, ct.index(), *initVal );
return true;
}
|
| ︙ | ︙ | |||
112 113 114 115 116 117 118 |
createTemporary( st, av.index(), pAlloca );
return true;
}
bool Module::buildInstruction( State& st, const cir::Load& load )
{
| | | | | 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
createTemporary( st, av.index(), pAlloca );
return true;
}
bool Module::buildInstruction( State& st, const cir::Load& load )
{
auto ptrVal = st.stack.pop( m_llvmBuilder );
if( !ptrVal )
return false;
auto type = LowerTypeForRuntime( st.context, *EIRToValue( load.type() ) );
if( !type )
return false;
auto* llvmType = GetLLVMType( *type );
assert( llvmType );
st.stack.push( m_llvmBuilder.CreateLoad( llvmType, *ptrVal ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::Store& store )
{
auto val = st.stack.pop( m_llvmBuilder );
if( !val )
return false;
auto ptrVal = st.stack.pop( m_llvmBuilder );
if( !ptrVal )
return false;
if( llvm::isa< llvm::ConstantAggregate >( *val ) )
{
stringstream name;
name << ".constaggr" << hex << m_nextAggregateID++;
|
| ︙ | ︙ |
Changes to bs/codegen/logicops.cpp.
1 2 3 4 5 6 7 8 9 |
#include "codegen.h"
#include "builtins/builtins.h"
using namespace goose;
using namespace goose::codegen;
using namespace goose::builtins;
bool Module::buildInstruction( State& st, const cir::Not& uo )
{
| | | | | | | | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
#include "codegen.h"
#include "builtins/builtins.h"
using namespace goose;
using namespace goose::codegen;
using namespace goose::builtins;
bool Module::buildInstruction( State& st, const cir::Not& uo )
{
auto operand = st.stack.pop( m_llvmBuilder );
if( !operand )
return false;
st.stack.push( m_llvmBuilder.CreateXor( *operand, llvm::ConstantInt::getTrue( GetLLVMContext() ) ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::And& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateAnd( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::Or& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateOr( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::Xor& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateXor( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::Shl& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateShl( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::LShr& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateLShr( *lhs, *rhs ) );
return true;
}
bool Module::buildInstruction( State& st, const cir::AShr& bo )
{
auto rhs = st.stack.pop( m_llvmBuilder );
if( !rhs )
return false;
auto lhs = st.stack.pop( m_llvmBuilder );
if( !lhs )
return false;
st.stack.push( m_llvmBuilder.CreateAShr( *lhs, *rhs ) );
return true;
}
|
Changes to bs/codegen/stack.h.
1 2 3 4 5 6 7 8 |
#ifndef GOOSE_CODEGEN_STACK_H
#define GOOSE_CODEGEN_STACK_H
namespace goose::codegen
{
class Stack
{
public:
| > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < | < < < < < | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
#ifndef GOOSE_CODEGEN_STACK_H
#define GOOSE_CODEGEN_STACK_H
namespace goose::codegen
{
class Stack
{
public:
using Slot = variant< llvm::Value*, codegen::Address >;
template< typename T = llvm::Value* >
optional< T > pop( llvm::IRBuilder<>& builder )
{
if( m_stack.empty() )
return nullopt;
auto result = m_stack.top();
m_stack.pop();
if constexpr( is_same_v< T, codegen::Address > )
{
if( !holds_alternative< codegen::Address >( result ) )
return nullopt;
return get< codegen::Address >( result );
}
else if constexpr( is_same_v< T, llvm::Value* > )
{
if( holds_alternative< codegen::Address >( result ) )
return AddressToGEP( builder, get< codegen::Address >( result ) );
else
return get< llvm::Value* >( result );
}
else if( holds_alternative< llvm::Value* >( result ) )
return llvm::dyn_cast_or_null< remove_pointer_t< T > >( get< llvm::Value* >( result ) );
return nullopt;
}
optional< Slot > pop()
{
if( m_stack.empty() )
return nullopt;
auto result = m_stack.top();
m_stack.pop();
return result;
}
template< typename T >
void push( T&& v )
{
m_stack.push( forward< T >( v ) );
}
private:
stack< Slot > m_stack;
};
}
#endif
|
Changes to bs/codegen/value.cpp.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 |
if( val.isConstant() )
return buildConstant( st, val );
if( !buildInstruction( st, *val.cir() ) )
return nullptr;
| | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
if( val.isConstant() )
return buildConstant( st, val );
if( !buildInstruction( st, *val.cir() ) )
return nullptr;
auto result = st.stack.pop( m_llvmBuilder );
if( !result )
return nullptr;
return *result;
}
llvm::Constant* Module::buildConstant( State& st, const Value& v )
|
| ︙ | ︙ |